Compare commits
404 Commits
github/for
...
v3.1.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89bfb517fb | ||
|
|
e1a1136e05 | ||
|
|
4c6f87f6e7 | ||
|
|
3613ad156b | ||
|
|
e50cb74d1d | ||
|
|
36800c6368 | ||
|
|
f67395c94c | ||
|
|
f8b9fe80fd | ||
|
|
e211517e24 | ||
|
|
538d3e5982 | ||
|
|
60e0b39f86 | ||
|
|
789bccf77a | ||
|
|
ce3ed6f17c | ||
|
|
54c6b1f1af | ||
|
|
dfb50e9a06 | ||
|
|
017954b646 | ||
|
|
73ac809bb3 | ||
|
|
c0f35c5c54 | ||
|
|
84b10eaa0b | ||
|
|
813b9e1586 | ||
|
|
92cdfa0526 | ||
|
|
a06333f716 | ||
|
|
01e3054ce9 | ||
|
|
549ea750c0 | ||
|
|
aab4197156 | ||
|
|
1bd32012d3 | ||
|
|
9f84538b76 | ||
|
|
e53f4808d5 | ||
|
|
9b9545fb8f | ||
|
|
cbfe831e0c | ||
|
|
7d277e0133 | ||
|
|
d072a14aa3 | ||
|
|
ddc8d67d84 | ||
|
|
a499aae31f | ||
|
|
aa0321df8f | ||
|
|
4aa7df65f5 | ||
|
|
8dbb0726d0 | ||
|
|
53b0c0b08f | ||
|
|
502f3b4aa7 | ||
|
|
85422837b0 | ||
|
|
26a35a902c | ||
|
|
f2a058c8c5 | ||
|
|
1b837377cb | ||
|
|
7c497977a2 | ||
|
|
8c1c86c374 | ||
|
|
9e714f811b | ||
|
|
a4754c947f | ||
|
|
fdced15e40 | ||
|
|
4c137d4602 | ||
|
|
711cbb906c | ||
|
|
2e6766f195 | ||
|
|
87bcfe90fe | ||
|
|
54886a2c5a | ||
|
|
550cd3b3d5 | ||
|
|
f1c83808fb | ||
|
|
fbe3276bac | ||
|
|
1479c15312 | ||
|
|
f738f91f24 | ||
|
|
aaecd203e1 | ||
|
|
4af5535f81 | ||
|
|
b5a9beb481 | ||
|
|
ed351109ba | ||
|
|
3ed5a2ff64 | ||
|
|
b8f5f90929 | ||
|
|
1115cc03b1 | ||
|
|
17879f9c70 | ||
|
|
1ff33be36f | ||
|
|
0f396b83f1 | ||
|
|
e02875ad56 | ||
|
|
230c24cca5 | ||
|
|
f853a2a39e | ||
|
|
843301c8b6 | ||
|
|
ea90b49604 | ||
|
|
cf39b426e1 | ||
|
|
b74035979f | ||
|
|
a3caa62ed3 | ||
|
|
2b44728c0e | ||
|
|
56217fbcf8 | ||
|
|
c9be6b6b92 | ||
|
|
07d0e86031 | ||
|
|
59846cfe2f | ||
|
|
ea3d922242 | ||
|
|
f9719c995c | ||
|
|
c755aa388b | ||
|
|
af2b422154 | ||
|
|
e463ee569a | ||
|
|
8f169ee113 | ||
|
|
b8c456eb71 | ||
|
|
35d14b33ca | ||
|
|
3aa8230e17 | ||
|
|
4476b1b216 | ||
|
|
12c827fe2a | ||
|
|
6db6c14016 | ||
|
|
3a1fa9ab00 | ||
|
|
fb8682e88d | ||
|
|
618d6f8337 | ||
|
|
214f7d3523 | ||
|
|
b439a1af3f | ||
|
|
602ee61cb6 | ||
|
|
4d0a75e61f | ||
|
|
cabddfb926 | ||
|
|
c20369fa57 | ||
|
|
d6b5fd1b9f | ||
|
|
4edf1ed41f | ||
|
|
4607665908 | ||
|
|
c9f8148acf | ||
|
|
1fd930b0a3 | ||
|
|
c9c6d5ee46 | ||
|
|
496924b2a4 | ||
|
|
32032e1c8a | ||
|
|
65b1ec9b1f | ||
|
|
7b724d4185 | ||
|
|
c8566dd2be | ||
|
|
79bb12ee61 | ||
|
|
db01980eb8 | ||
|
|
859d849d36 | ||
|
|
855f0aa334 | ||
|
|
313ebc6055 | ||
|
|
041b7d520c | ||
|
|
93bc7c690f | ||
|
|
58a8f6fd6e | ||
|
|
1522b00579 | ||
|
|
93712a7f5e | ||
|
|
abb3db4e30 | ||
|
|
bd184fceda | ||
|
|
93ef0c256e | ||
|
|
fd5b2e08a5 | ||
|
|
1a286df3f7 | ||
|
|
06e59fdfa0 | ||
|
|
9884a39abc | ||
|
|
90b320952b | ||
|
|
4b8569bd5e | ||
|
|
5714c23073 | ||
|
|
09ea3b27f4 | ||
|
|
5fbf0baa0f | ||
|
|
2c09520f98 | ||
|
|
87189c070e | ||
|
|
81cded0052 | ||
|
|
89cd970d5a | ||
|
|
c2b7fb4823 | ||
|
|
f37b92261f | ||
|
|
b28d34cf66 | ||
|
|
a21c3dcdf1 | ||
|
|
59655a819a | ||
|
|
d3450c5f65 | ||
|
|
3af0ae9f85 | ||
|
|
a557bbb948 | ||
|
|
e78de55fe7 | ||
|
|
065ea0c6fe | ||
|
|
9b22251705 | ||
|
|
721d0c6da1 | ||
|
|
170ac28bb5 | ||
|
|
3be9053b76 | ||
|
|
ede1dbc5e7 | ||
|
|
5551125865 | ||
|
|
eb744346f0 | ||
|
|
5d5ce092b7 | ||
|
|
109c12064d | ||
|
|
c9a553c5d3 | ||
|
|
1fae3066fa | ||
|
|
c8d1b2c19a | ||
|
|
be89e0d60b | ||
|
|
076f33605a | ||
|
|
eaf099d2ce | ||
|
|
007731b71c | ||
|
|
0ca6c2cbff | ||
|
|
94f0df096d | ||
|
|
55ed27511f | ||
|
|
294700a6ca | ||
|
|
dfe70a5a95 | ||
|
|
bc98f7c55e | ||
|
|
e2d16ba63e | ||
|
|
4f7255a8d9 | ||
|
|
ad59fcd3e9 | ||
|
|
5222d319a3 | ||
|
|
1f3a6a9da6 | ||
|
|
d687c156ff | ||
|
|
e95407e6f5 | ||
|
|
23f9b5228c | ||
|
|
ac0d0efe0f | ||
|
|
4c3eb98041 | ||
|
|
ce2cf89fd6 | ||
|
|
347e38c413 | ||
|
|
3a964dcf17 | ||
|
|
f2714bd0ab | ||
|
|
66a8170fd2 | ||
|
|
9f8269d9a9 | ||
|
|
64745b9147 | ||
|
|
b0bf33191b | ||
|
|
500db90974 | ||
|
|
e5f575705f | ||
|
|
1acafe5b8f | ||
|
|
fcfaae7b58 | ||
|
|
311b011ec6 | ||
|
|
efcf778c95 | ||
|
|
149c278e22 | ||
|
|
431ad2ff2c | ||
|
|
93a77dc027 | ||
|
|
e5c6b54e7b | ||
|
|
859dbb8655 | ||
|
|
6c2f25a9a3 | ||
|
|
75140ccf97 | ||
|
|
df46f1f1d0 | ||
|
|
166e53ceaa | ||
|
|
165e346d38 | ||
|
|
8485544731 | ||
|
|
feb325c2c7 | ||
|
|
c611ff2229 | ||
|
|
e75b2960c0 | ||
|
|
1ffb9828f7 | ||
|
|
fee1a92715 | ||
|
|
8d7553e1cc | ||
|
|
a40638b657 | ||
|
|
d9adc49e9f | ||
|
|
5607f6d524 | ||
|
|
d821fd7800 | ||
|
|
e87f287476 | ||
|
|
c2a52d3c18 | ||
|
|
08d320ad1c | ||
|
|
d17abdcd11 | ||
|
|
19485b5ba1 | ||
|
|
1ea98613fb | ||
|
|
b8b000d88c | ||
|
|
1e99dae9de | ||
|
|
1e78532dc5 | ||
|
|
454beff2d3 | ||
|
|
6f417d23d1 | ||
|
|
58cbf78fb9 | ||
|
|
ff917b7ecf | ||
|
|
b2d6d7e736 | ||
|
|
95d320a0fe | ||
|
|
fd8c57bff0 | ||
|
|
36cb1e1103 | ||
|
|
77e0be8234 | ||
|
|
4b93b91373 | ||
|
|
639c7ef1e6 | ||
|
|
95ae59c7a3 | ||
|
|
9e73a44426 | ||
|
|
2c93312df0 | ||
|
|
09cf207ecc | ||
|
|
1d13b7bede | ||
|
|
5b104ecb42 | ||
|
|
235045dec4 | ||
|
|
fa273a13f2 | ||
|
|
d8b59cae05 | ||
|
|
45f2727415 | ||
|
|
7e44b3dedb | ||
|
|
0dea700479 | ||
|
|
56247eaf7b | ||
|
|
590a15e534 | ||
|
|
fb1cc9b82c | ||
|
|
7595f19af3 | ||
|
|
e978d84f5f | ||
|
|
0157d546e4 | ||
|
|
4f5dc51a68 | ||
|
|
938650dbde | ||
|
|
bae9e57fcd | ||
|
|
6a673f0c6b | ||
|
|
a962d839a8 | ||
|
|
173fb41e63 | ||
|
|
26cbeee5af | ||
|
|
f6b5263814 | ||
|
|
3b7ddd0170 | ||
|
|
600cbfe861 | ||
|
|
994f4568a4 | ||
|
|
1de973ebd0 | ||
|
|
4f6d3d7057 | ||
|
|
124e38c782 | ||
|
|
c9eed85a00 | ||
|
|
988c01f506 | ||
|
|
5450443022 | ||
|
|
590a1b354d | ||
|
|
2dcb629c2d | ||
|
|
96feaf8d42 | ||
|
|
4cb3258e17 | ||
|
|
9b9b3f73d0 | ||
|
|
de36965017 | ||
|
|
e9fddd2456 | ||
|
|
8b4791f1f4 | ||
|
|
281208a8aa | ||
|
|
5f9397f6db | ||
|
|
870e45991b | ||
|
|
38e94c92d7 | ||
|
|
93fbf7657d | ||
|
|
0fc6d69851 | ||
|
|
7f600a0cbf | ||
|
|
d7e06d6622 | ||
|
|
c6d4b658a1 | ||
|
|
a847f9370c | ||
|
|
fe8f962fb0 | ||
|
|
4060f7a1a6 | ||
|
|
5bc424796a | ||
|
|
7f33b63bed | ||
|
|
2d8b63c803 | ||
|
|
6259cf4104 | ||
|
|
f35c34fa63 | ||
|
|
57e0fb493f | ||
|
|
730ea4f2b9 | ||
|
|
948965dda5 | ||
|
|
f2cc20cb7c | ||
|
|
46c3b33548 | ||
|
|
7785d42021 | ||
|
|
130c23603f | ||
|
|
330341392d | ||
|
|
9d1c04d07a | ||
|
|
94ef1679a9 | ||
|
|
ca953de464 | ||
|
|
2c1c3e3c98 | ||
|
|
40ec773425 | ||
|
|
a7b8018ed9 | ||
|
|
8cfe5b4d34 | ||
|
|
a2e41b81a3 | ||
|
|
ee4639e041 | ||
|
|
6e6469d90f | ||
|
|
a53793a76b | ||
|
|
d046f1ed21 | ||
|
|
da1ac788fb | ||
|
|
1980560a2d | ||
|
|
1416cd46a3 | ||
|
|
610b6e528c | ||
|
|
f66bdd706b | ||
|
|
518d919da5 | ||
|
|
9619578fcf | ||
|
|
56687948bf | ||
|
|
7166f66a9e | ||
|
|
8ec52bf193 | ||
|
|
cc3fc10ddf | ||
|
|
15ecba1f6e | ||
|
|
2828640ed7 | ||
|
|
c314c397a5 | ||
|
|
341903fc3e | ||
|
|
5078946191 | ||
|
|
7c039ead10 | ||
|
|
20c001914a | ||
|
|
77e9de704d | ||
|
|
34ec8467ec | ||
|
|
94b65c0357 | ||
|
|
b32952f076 | ||
|
|
eeae140a41 | ||
|
|
e277af0e4b | ||
|
|
8a67492cf8 | ||
|
|
c556a00e4a | ||
|
|
9c9c0e6c09 | ||
|
|
21ca26dcfe | ||
|
|
981dbceb93 | ||
|
|
aaee27732d | ||
|
|
e7acce2dfc | ||
|
|
56b15bf52a | ||
|
|
2f8fe67f9f | ||
|
|
b09e91a1cf | ||
|
|
9418c4acf7 | ||
|
|
0451bc55aa | ||
|
|
2840110a21 | ||
|
|
8c4eacf045 | ||
|
|
179785432d | ||
|
|
c3da39205f | ||
|
|
f071d1006b | ||
|
|
6da1832799 | ||
|
|
df0e124c3a | ||
|
|
25f1a72b48 | ||
|
|
2b5e76ffdd | ||
|
|
9d75e3ad6f | ||
|
|
ab5024ec4a | ||
|
|
bdaf4d6d9b | ||
|
|
6d53aaa631 | ||
|
|
e67d605949 | ||
|
|
b82840df3b | ||
|
|
42e0df29ee | ||
|
|
0745f5b401 | ||
|
|
1ab5b8bd00 | ||
|
|
dc93ef9134 | ||
|
|
943cfc2913 | ||
|
|
6b125aff27 | ||
|
|
3469b624d5 | ||
|
|
c498e331c7 | ||
|
|
c8165c10bf | ||
|
|
8af29abd92 | ||
|
|
5662ddd2be | ||
|
|
8f1e71010b | ||
|
|
71ff6c3c44 | ||
|
|
74cd60ff3d | ||
|
|
d09a441faa | ||
|
|
bef9ec30f9 | ||
|
|
3e33e1f4b3 | ||
|
|
c8485adac5 | ||
|
|
d623828fe5 | ||
|
|
0f5c7af703 | ||
|
|
b965d3aa0e | ||
|
|
93d12a9fb6 | ||
|
|
ce239e0e20 | ||
|
|
09af1d1f89 | ||
|
|
3b828ca0f4 | ||
|
|
4f4dd29e5f | ||
|
|
9189541c3a | ||
|
|
9ee4e2e29b | ||
|
|
fd80b85786 | ||
|
|
119af47d77 | ||
|
|
a419b9ae38 | ||
|
|
7d4d434164 | ||
|
|
5d304f9e13 | ||
|
|
a45e06efa3 | ||
|
|
e7292eb75e | ||
|
|
39f731352f | ||
|
|
9fa9f6d85a |
@@ -1,5 +1,2 @@
|
||||
MAIN_VITE_API_URL=API_URL
|
||||
MAIN_VITE_AUTH_URL=AUTH_URL
|
||||
MAIN_VITE_STEAMGRIDDB_API_KEY=YOUR_API_KEY
|
||||
MAIN_VITE_SENTRY_DSN=YOUR_SENTRY_DSN
|
||||
SENTRY_AUTH_TOKEN=
|
||||
|
||||
@@ -3,3 +3,4 @@ dist
|
||||
out
|
||||
.gitignore
|
||||
migration.stub
|
||||
hydra-python-rpc/
|
||||
|
||||
@@ -26,4 +26,9 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
},
|
||||
settings: {
|
||||
react: {
|
||||
version: "detect",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
28
.github/workflows/build.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.11.1
|
||||
node-version: 20.18.0
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
run: pip install -r requirements.txt
|
||||
|
||||
- name: Build with cx_Freeze
|
||||
run: python torrent-client/setup.py build
|
||||
run: python python_rpc/setup.py build
|
||||
|
||||
- name: Build Linux
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
@@ -43,9 +43,11 @@ jobs:
|
||||
MAIN_VITE_API_URL: ${{ vars.MAIN_VITE_STAGING_API_URL }}
|
||||
MAIN_VITE_AUTH_URL: ${{ vars.MAIN_VITE_STAGING_AUTH_URL }}
|
||||
MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_STAGING_CHECKOUT_URL }}
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
MAIN_VITE_SENTRY_DSN: ${{ vars.MAIN_VITE_SENTRY_DSN }}
|
||||
MAIN_VITE_ANALYTICS_API_URL: ${{ vars.MAIN_VITE_ANALYTICS_API_URL }}
|
||||
RENDERER_VITE_INTERCOM_APP_ID: ${{ vars.RENDERER_VITE_INTERCOM_APP_ID }}
|
||||
RENDERER_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.RENDERER_VITE_EXTERNAL_RESOURCES_URL }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
MAIN_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.MAIN_VITE_EXTERNAL_RESOURCES_URL }}
|
||||
|
||||
- name: Build Windows
|
||||
if: matrix.os == 'windows-latest'
|
||||
@@ -54,9 +56,23 @@ jobs:
|
||||
MAIN_VITE_API_URL: ${{ vars.MAIN_VITE_STAGING_API_URL }}
|
||||
MAIN_VITE_AUTH_URL: ${{ vars.MAIN_VITE_STAGING_AUTH_URL }}
|
||||
MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_STAGING_CHECKOUT_URL }}
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
MAIN_VITE_SENTRY_DSN: ${{ vars.MAIN_VITE_SENTRY_DSN }}
|
||||
MAIN_VITE_ANALYTICS_API_URL: ${{ vars.MAIN_VITE_ANALYTICS_API_URL }}
|
||||
RENDERER_VITE_INTERCOM_APP_ID: ${{ vars.RENDERER_VITE_INTERCOM_APP_ID }}
|
||||
RENDERER_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.RENDERER_VITE_EXTERNAL_RESOURCES_URL }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
MAIN_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.MAIN_VITE_EXTERNAL_RESOURCES_URL }}
|
||||
|
||||
- name: Test Upload build
|
||||
env:
|
||||
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
||||
S3_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
|
||||
S3_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
|
||||
S3_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
|
||||
S3_BUILDS_BUCKET_NAME: ${{ secrets.S3_BUILDS_BUCKET_NAME }}
|
||||
BUILDS_URL: ${{ secrets.BUILDS_URL }}
|
||||
BUILD_WEBHOOK_URL: ${{ secrets.BUILD_WEBHOOK_URL }}
|
||||
GITHUB_ACTOR: ${{ github.actor }}
|
||||
run: node scripts/upload-build.cjs
|
||||
|
||||
- name: Create artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
2
.github/workflows/lint.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.11.1
|
||||
node-version: 20.18.0
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn
|
||||
|
||||
20
.github/workflows/release.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.11.1
|
||||
node-version: 20.18.0
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
run: pip install -r requirements.txt
|
||||
|
||||
- name: Build with cx_Freeze
|
||||
run: python torrent-client/setup.py build
|
||||
run: python python_rpc/setup.py build
|
||||
|
||||
- name: Build Linux
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
@@ -45,10 +45,11 @@ jobs:
|
||||
MAIN_VITE_API_URL: ${{ vars.MAIN_VITE_API_URL }}
|
||||
MAIN_VITE_AUTH_URL: ${{ vars.MAIN_VITE_AUTH_URL }}
|
||||
MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_CHECKOUT_URL }}
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
MAIN_VITE_SENTRY_DSN: ${{ vars.MAIN_VITE_SENTRY_DSN }}
|
||||
MAIN_VITE_ANALYTICS_API_URL: ${{ vars.MAIN_VITE_ANALYTICS_API_URL }}
|
||||
RENDERER_VITE_INTERCOM_APP_ID: ${{ vars.RENDERER_VITE_INTERCOM_APP_ID }}
|
||||
RENDERER_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.RENDERER_VITE_EXTERNAL_RESOURCES_URL }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
MAIN_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.MAIN_VITE_EXTERNAL_RESOURCES_URL }}
|
||||
- name: Build Windows
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: yarn build:win
|
||||
@@ -56,10 +57,11 @@ jobs:
|
||||
MAIN_VITE_API_URL: ${{ vars.MAIN_VITE_API_URL }}
|
||||
MAIN_VITE_AUTH_URL: ${{ vars.MAIN_VITE_AUTH_URL }}
|
||||
MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_CHECKOUT_URL }}
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
MAIN_VITE_SENTRY_DSN: ${{ vars.MAIN_VITE_SENTRY_DSN }}
|
||||
MAIN_VITE_ANALYTICS_API_URL: ${{ vars.MAIN_VITE_ANALYTICS_API_URL }}
|
||||
RENDERER_VITE_INTERCOM_APP_ID: ${{ vars.RENDERER_VITE_INTERCOM_APP_ID }}
|
||||
RENDERER_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.RENDERER_VITE_EXTERNAL_RESOURCES_URL }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
MAIN_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.MAIN_VITE_EXTERNAL_RESOURCES_URL }}
|
||||
- name: Create artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -77,7 +79,7 @@ jobs:
|
||||
dist/*.pacman
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
draft: true
|
||||
files: |
|
||||
|
||||
7
.gitignore
vendored
@@ -1,7 +1,5 @@
|
||||
.vscode/
|
||||
node_modules/
|
||||
hydra-download-manager/
|
||||
fastlist.exe
|
||||
__pycache__
|
||||
dist
|
||||
out
|
||||
@@ -9,5 +7,6 @@ out
|
||||
*.log*
|
||||
.env
|
||||
.vite
|
||||
sentry.properties
|
||||
ludusavi/
|
||||
ludusavi/
|
||||
hydra-python-rpc/
|
||||
aria2/
|
||||
|
||||
1
.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.9.20
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
||||
[<img src="./resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||
|
||||
<h1 align="center">Hydra Launcher</h1>
|
||||
|
||||
@@ -125,6 +125,10 @@ cd hydra
|
||||
yarn
|
||||
```
|
||||
|
||||
### Install OpenSSL 1.1
|
||||
|
||||
[OpenSSL 1.1](https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe) is required by libtorrent in Windows environments.
|
||||
|
||||
### 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-3913/).
|
||||
|
||||
BIN
build/icon.ico
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 108 KiB |
BIN
build/icon.png
|
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 604 KiB |
@@ -2,7 +2,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
||||
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||
|
||||
<h1 align="center">Hydra Launcher</h1>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
||||
[<img src="./resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||
|
||||
<h1 align="center">Hydra Launcher</h1>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
||||
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||
|
||||
<h1 align="center">Hydra Launcher</h1>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
||||
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||
|
||||
<h1 align="center">Hydra Launcher</h1>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
||||
[<img src="./resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||
|
||||
<h1 align="center">Hydra Launcher</h1>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div align="center">
|
||||
|
||||
[<img src="../resources/icon.png" width="144"/>](https://hydralauncher.site)
|
||||
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||
|
||||
<h1 align="center">Hydra Launcher</h1>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
||||
[<img src="./resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||
|
||||
<h1 align="center">Hydra Launcher</h1>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
||||
[<img src="./resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||
|
||||
<h1 align="center">Hydra Launcher</h1>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
||||
[<img src="./resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||
|
||||
<h1 align="center">Hydra Launcher</h1>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
||||
[<img src="./resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||
|
||||
<h1 align="center">Hydra Launcher</h1>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
||||
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||
|
||||
<h1 align="center">Hydra Launcher</h1>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
[](https://github.com/hydralauncher/hydra/releases)
|
||||
|
||||
[](README.pt-BR.md)
|
||||
[](README.md)
|
||||
[](../README.md)
|
||||
[](README.ru.md)
|
||||
[](README.uk-UA.md)
|
||||
[](README.be.md)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
||||
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||
|
||||
<h1 align="center">Hydra Launcher</h1>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
[](https://github.com/hydralauncher/hydra/releases)
|
||||
|
||||
[](README.pt-BR.md)
|
||||
[](README.md)
|
||||
[](../README.md)
|
||||
[](README.ru.md)
|
||||
[](README.uk-UA.md)
|
||||
[](README.be.md)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
|
||||
[<img src="./resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
|
||||
|
||||
<h1 align="center">Hydra Launcher</h1>
|
||||
|
||||
|
||||
@@ -3,10 +3,12 @@ productName: Hydra
|
||||
directories:
|
||||
buildResources: build
|
||||
extraResources:
|
||||
- aria2
|
||||
- ludusavi
|
||||
- hydra-download-manager
|
||||
- hydra-python-rpc
|
||||
- seeds
|
||||
- from: node_modules/create-desktop-shortcuts/src/windows.vbs
|
||||
- from: resources/achievement.wav
|
||||
files:
|
||||
- "!**/.vscode/*"
|
||||
- "!src/*"
|
||||
|
||||
@@ -6,16 +6,9 @@ import {
|
||||
externalizeDepsPlugin,
|
||||
} from "electron-vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import { sentryVitePlugin } from "@sentry/vite-plugin";
|
||||
import { vanillaExtractPlugin } from "@vanilla-extract/vite-plugin";
|
||||
import svgr from "vite-plugin-svgr";
|
||||
|
||||
const sentryPlugin = sentryVitePlugin({
|
||||
authToken: process.env.SENTRY_AUTH_TOKEN,
|
||||
org: "hydra-launcher",
|
||||
project: "hydra-launcher",
|
||||
});
|
||||
|
||||
export default defineConfig(({ mode }) => {
|
||||
loadEnv(mode);
|
||||
|
||||
@@ -35,7 +28,7 @@ export default defineConfig(({ mode }) => {
|
||||
"@shared": resolve("src/shared"),
|
||||
},
|
||||
},
|
||||
plugins: [externalizeDepsPlugin(), swcPlugin(), sentryPlugin],
|
||||
plugins: [externalizeDepsPlugin(), swcPlugin()],
|
||||
},
|
||||
preload: {
|
||||
plugins: [externalizeDepsPlugin()],
|
||||
@@ -51,7 +44,7 @@ export default defineConfig(({ mode }) => {
|
||||
"@shared": resolve("src/shared"),
|
||||
},
|
||||
},
|
||||
plugins: [svgr(), react(), vanillaExtractPlugin(), sentryPlugin],
|
||||
plugins: [svgr(), react(), vanillaExtractPlugin()],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
60
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hydralauncher",
|
||||
"version": "3.0.4",
|
||||
"version": "3.1.2",
|
||||
"description": "Hydra",
|
||||
"main": "./out/main/index.js",
|
||||
"author": "Los Broxas",
|
||||
@@ -23,7 +23,7 @@
|
||||
"start": "electron-vite preview",
|
||||
"dev": "electron-vite dev",
|
||||
"build": "npm run typecheck && electron-vite build",
|
||||
"postinstall": "electron-builder install-app-deps && node ./postinstall.cjs",
|
||||
"postinstall": "electron-builder install-app-deps && node ./scripts/postinstall.cjs",
|
||||
"build:unpack": "npm run build && electron-builder --dir",
|
||||
"build:win": "electron-vite build && electron-builder --win",
|
||||
"build:mac": "electron-vite build && electron-builder --mac",
|
||||
@@ -34,82 +34,84 @@
|
||||
"dependencies": {
|
||||
"@electron-toolkit/preload": "^3.0.0",
|
||||
"@electron-toolkit/utils": "^3.0.0",
|
||||
"@fontsource/noto-sans": "^5.0.22",
|
||||
"@hookform/resolvers": "^3.9.0",
|
||||
"@fontsource/noto-sans": "^5.1.0",
|
||||
"@hookform/resolvers": "^3.9.1",
|
||||
"@primer/octicons-react": "^19.9.0",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.2",
|
||||
"@reduxjs/toolkit": "^2.2.3",
|
||||
"@sentry/electron": "^5.1.0",
|
||||
"@vanilla-extract/css": "^1.14.2",
|
||||
"@vanilla-extract/dynamic": "^2.1.1",
|
||||
"@vanilla-extract/dynamic": "^2.1.2",
|
||||
"@vanilla-extract/recipes": "^0.5.2",
|
||||
"auto-launch": "^5.0.6",
|
||||
"axios": "^1.7.7",
|
||||
"better-sqlite3": "^11.3.0",
|
||||
"axios": "^1.7.9",
|
||||
"better-sqlite3": "^11.7.0",
|
||||
"check-disk-space": "^3.4.0",
|
||||
"classnames": "^2.5.1",
|
||||
"color": "^4.2.3",
|
||||
"color.js": "^1.2.0",
|
||||
"create-desktop-shortcuts": "^1.11.0",
|
||||
"date-fns": "^3.6.0",
|
||||
"dexie": "^4.0.8",
|
||||
"electron-log": "^5.2.0",
|
||||
"dexie": "^4.0.10",
|
||||
"electron-log": "^5.2.4",
|
||||
"electron-updater": "^6.3.9",
|
||||
"flexsearch": "^0.7.43",
|
||||
"file-type": "^19.6.0",
|
||||
"i18next": "^23.11.2",
|
||||
"i18next-browser-languagedetector": "^7.2.1",
|
||||
"icojs": "^0.19.4",
|
||||
"jsdom": "^24.0.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"knex": "^3.1.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lottie-react": "^2.4.0",
|
||||
"parse-torrent": "^11.0.17",
|
||||
"piscina": "^4.5.1",
|
||||
"piscina": "^4.7.0",
|
||||
"rc-virtual-list": "^3.16.1",
|
||||
"react-hook-form": "^7.53.0",
|
||||
"react-i18next": "^14.1.0",
|
||||
"react-loading-skeleton": "^3.4.0",
|
||||
"react-redux": "^9.1.1",
|
||||
"react-router-dom": "^6.22.3",
|
||||
"sound-play": "^1.1.0",
|
||||
"sudo-prompt": "^9.2.1",
|
||||
"tar": "^7.4.3",
|
||||
"typeorm": "^0.3.20",
|
||||
"user-agents": "^1.1.193",
|
||||
"yaml": "^2.4.1",
|
||||
"yup": "^1.4.0",
|
||||
"zod": "^3.23.8"
|
||||
"user-agents": "^1.1.387",
|
||||
"yaml": "^2.6.1",
|
||||
"yup": "^1.5.0",
|
||||
"zod": "^3.24.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^19.3.0",
|
||||
"@commitlint/config-conventional": "^19.2.2",
|
||||
"@aws-sdk/client-s3": "^3.705.0",
|
||||
"@commitlint/cli": "^19.6.0",
|
||||
"@commitlint/config-conventional": "^19.6.0",
|
||||
"@electron-toolkit/eslint-config-prettier": "^2.0.0",
|
||||
"@electron-toolkit/eslint-config-ts": "^1.0.1",
|
||||
"@electron-toolkit/eslint-config-ts": "^2.0.0",
|
||||
"@electron-toolkit/tsconfig": "^1.0.1",
|
||||
"@sentry/vite-plugin": "^2.20.1",
|
||||
"@swc/core": "^1.4.16",
|
||||
"@types/auto-launch": "^5.0.5",
|
||||
"@types/color": "^3.0.6",
|
||||
"@types/folder-hash": "^4.0.4",
|
||||
"@types/jsdom": "^21.1.6",
|
||||
"@types/jsonwebtoken": "^9.0.6",
|
||||
"@types/jsdom": "^21.1.7",
|
||||
"@types/jsonwebtoken": "^9.0.7",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^20.12.7",
|
||||
"@types/parse-torrent": "^5.8.7",
|
||||
"@types/react": "^18.2.48",
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"@types/sound-play": "^1.1.3",
|
||||
"@types/user-agents": "^1.0.4",
|
||||
"@vanilla-extract/vite-plugin": "^4.0.7",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"electron": "^30.3.0",
|
||||
"electron": "^31.7.6",
|
||||
"electron-builder": "^25.1.8",
|
||||
"electron-vite": "^2.0.0",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||
"eslint-plugin-react": "^7.37.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"husky": "^9.0.11",
|
||||
"prettier": "^3.2.4",
|
||||
"husky": "^9.1.7",
|
||||
"prettier": "^3.4.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"sass-embedded": "^1.80.6",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.0.12",
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
const { default: axios } = require("axios");
|
||||
const util = require("node:util");
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
|
||||
const exec = util.promisify(require("node:child_process").exec);
|
||||
|
||||
const fileName = {
|
||||
win32: "ludusavi-v0.25.0-win64.zip",
|
||||
linux: "ludusavi-v0.25.0-linux.zip",
|
||||
darwin: "ludusavi-v0.25.0-mac.zip",
|
||||
};
|
||||
|
||||
const downloadLudusavi = async () => {
|
||||
if (fs.existsSync("ludusavi")) {
|
||||
console.log("Ludusavi already exists, skipping download...");
|
||||
return;
|
||||
}
|
||||
|
||||
const file = fileName[process.platform];
|
||||
const downloadUrl = `https://github.com/mtkennerly/ludusavi/releases/download/v0.25.0/${file}`;
|
||||
|
||||
console.log(`Downloading ${file}...`);
|
||||
|
||||
const response = await axios.get(downloadUrl, { responseType: "stream" });
|
||||
|
||||
const stream = response.data.pipe(fs.createWriteStream(file));
|
||||
|
||||
stream.on("finish", async () => {
|
||||
console.log(`Downloaded ${file}, extracting...`);
|
||||
|
||||
const pwd = process.cwd();
|
||||
|
||||
const targetPath = path.join(pwd, "ludusavi");
|
||||
|
||||
await exec(`npx extract-zip ${file} ${targetPath}`);
|
||||
|
||||
if (process.platform !== "win32") {
|
||||
fs.chmodSync(path.join(targetPath, "ludusavi"), 0o755);
|
||||
}
|
||||
|
||||
console.log("Extracted. Renaming folder...");
|
||||
|
||||
console.log(`Extracted ${file}, removing compressed downloaded file...`);
|
||||
fs.rmSync(file);
|
||||
});
|
||||
};
|
||||
|
||||
downloadLudusavi();
|
||||
47
python_rpc/http_downloader.py
Normal file
@@ -0,0 +1,47 @@
|
||||
import aria2p
|
||||
|
||||
class HttpDownloader:
|
||||
def __init__(self):
|
||||
self.download = None
|
||||
self.aria2 = aria2p.API(
|
||||
aria2p.Client(
|
||||
host="http://localhost",
|
||||
port=6800,
|
||||
secret=""
|
||||
)
|
||||
)
|
||||
|
||||
def start_download(self, url: str, save_path: str, header: str):
|
||||
if self.download:
|
||||
self.aria2.resume([self.download])
|
||||
else:
|
||||
downloads = self.aria2.add(url, options={"header": header, "dir": save_path})
|
||||
self.download = downloads[0]
|
||||
|
||||
def pause_download(self):
|
||||
if self.download:
|
||||
self.aria2.pause([self.download])
|
||||
|
||||
def cancel_download(self):
|
||||
if self.download:
|
||||
self.aria2.remove([self.download])
|
||||
self.download = None
|
||||
|
||||
def get_download_status(self):
|
||||
if self.download == None:
|
||||
return None
|
||||
|
||||
download = self.aria2.get_download(self.download.gid)
|
||||
|
||||
response = {
|
||||
'folderName': download.name,
|
||||
'fileSize': download.total_length,
|
||||
'progress': download.completed_length / download.total_length if download.total_length else 0,
|
||||
'downloadSpeed': download.download_speed,
|
||||
'numPeers': 0,
|
||||
'numSeeds': 0,
|
||||
'status': download.status,
|
||||
'bytesDownloaded': download.completed_length,
|
||||
}
|
||||
|
||||
return response
|
||||
183
python_rpc/main.py
Normal file
@@ -0,0 +1,183 @@
|
||||
from flask import Flask, request, jsonify
|
||||
import sys, json, urllib.parse, psutil
|
||||
from torrent_downloader import TorrentDownloader
|
||||
from http_downloader import HttpDownloader
|
||||
from profile_image_processor import ProfileImageProcessor
|
||||
import libtorrent as lt
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# Retrieve command line arguments
|
||||
torrent_port = sys.argv[1]
|
||||
http_port = sys.argv[2]
|
||||
rpc_password = sys.argv[3]
|
||||
start_download_payload = sys.argv[4]
|
||||
start_seeding_payload = sys.argv[5]
|
||||
|
||||
downloads = {}
|
||||
# This can be streamed down from Node
|
||||
downloading_game_id = -1
|
||||
|
||||
torrent_session = lt.session({'listen_interfaces': '0.0.0.0:{port}'.format(port=torrent_port)})
|
||||
|
||||
if start_download_payload:
|
||||
initial_download = json.loads(urllib.parse.unquote(start_download_payload))
|
||||
downloading_game_id = initial_download['game_id']
|
||||
|
||||
if initial_download['url'].startswith('magnet'):
|
||||
torrent_downloader = TorrentDownloader(torrent_session)
|
||||
downloads[initial_download['game_id']] = torrent_downloader
|
||||
try:
|
||||
torrent_downloader.start_download(initial_download['url'], initial_download['save_path'], "")
|
||||
except Exception as e:
|
||||
print("Error starting torrent download", e)
|
||||
else:
|
||||
http_downloader = HttpDownloader()
|
||||
downloads[initial_download['game_id']] = http_downloader
|
||||
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:
|
||||
initial_seeding = json.loads(urllib.parse.unquote(start_seeding_payload))
|
||||
for seed in initial_seeding:
|
||||
torrent_downloader = TorrentDownloader(torrent_session, lt.torrent_flags.upload_mode)
|
||||
downloads[seed['game_id']] = torrent_downloader
|
||||
try:
|
||||
torrent_downloader.start_download(seed['url'], seed['save_path'], "")
|
||||
except Exception as e:
|
||||
print("Error starting seeding", e)
|
||||
|
||||
def validate_rpc_password():
|
||||
"""Middleware to validate RPC password."""
|
||||
header_password = request.headers.get('x-hydra-rpc-password')
|
||||
if header_password != rpc_password:
|
||||
return jsonify({"error": "Unauthorized"}), 401
|
||||
|
||||
@app.route("/status", methods=["GET"])
|
||||
def status():
|
||||
auth_error = validate_rpc_password()
|
||||
if auth_error:
|
||||
return auth_error
|
||||
|
||||
downloader = downloads.get(downloading_game_id)
|
||||
if downloader:
|
||||
status = downloads.get(downloading_game_id).get_download_status()
|
||||
return jsonify(status), 200
|
||||
else:
|
||||
return jsonify(None)
|
||||
|
||||
@app.route("/seed-status", methods=["GET"])
|
||||
def seed_status():
|
||||
auth_error = validate_rpc_password()
|
||||
if auth_error:
|
||||
return auth_error
|
||||
|
||||
seed_status = []
|
||||
|
||||
for game_id, downloader in downloads.items():
|
||||
if not downloader:
|
||||
continue
|
||||
|
||||
response = downloader.get_download_status()
|
||||
if response is None:
|
||||
continue
|
||||
|
||||
if response.get('status') == 5:
|
||||
seed_status.append({
|
||||
'gameId': game_id,
|
||||
**response,
|
||||
})
|
||||
|
||||
return jsonify(seed_status), 200
|
||||
|
||||
@app.route("/healthcheck", methods=["GET"])
|
||||
def healthcheck():
|
||||
return "", 200
|
||||
|
||||
@app.route("/process-list", methods=["GET"])
|
||||
def process_list():
|
||||
auth_error = validate_rpc_password()
|
||||
if auth_error:
|
||||
return auth_error
|
||||
|
||||
process_list = [proc.info for proc in psutil.process_iter(['exe', 'pid', 'name'])]
|
||||
return jsonify(process_list), 200
|
||||
|
||||
@app.route("/profile-image", methods=["POST"])
|
||||
def profile_image():
|
||||
auth_error = validate_rpc_password()
|
||||
if auth_error:
|
||||
return auth_error
|
||||
|
||||
data = request.get_json()
|
||||
image_path = data.get('image_path')
|
||||
|
||||
try:
|
||||
processed_image_path, mime_type = ProfileImageProcessor.process_image(image_path)
|
||||
return jsonify({'imagePath': processed_image_path, 'mimeType': mime_type}), 200
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 400
|
||||
|
||||
@app.route("/action", methods=["POST"])
|
||||
def action():
|
||||
global torrent_session
|
||||
global downloading_game_id
|
||||
|
||||
auth_error = validate_rpc_password()
|
||||
if auth_error:
|
||||
return auth_error
|
||||
|
||||
data = request.get_json()
|
||||
action = data.get('action')
|
||||
game_id = data.get('game_id')
|
||||
|
||||
if action == 'start':
|
||||
url = data.get('url')
|
||||
|
||||
existing_downloader = downloads.get(game_id)
|
||||
|
||||
if url.startswith('magnet'):
|
||||
if existing_downloader and isinstance(existing_downloader, TorrentDownloader):
|
||||
existing_downloader.start_download(url, data['save_path'], "")
|
||||
else:
|
||||
torrent_downloader = TorrentDownloader(torrent_session)
|
||||
downloads[game_id] = torrent_downloader
|
||||
torrent_downloader.start_download(url, data['save_path'], "")
|
||||
else:
|
||||
if existing_downloader and isinstance(existing_downloader, HttpDownloader):
|
||||
existing_downloader.start_download(url, data['save_path'], data.get('header'))
|
||||
else:
|
||||
http_downloader = HttpDownloader()
|
||||
downloads[game_id] = http_downloader
|
||||
http_downloader.start_download(url, data['save_path'], data.get('header'))
|
||||
|
||||
downloading_game_id = game_id
|
||||
|
||||
elif action == 'pause':
|
||||
downloader = downloads.get(game_id)
|
||||
if downloader:
|
||||
downloader.pause_download()
|
||||
downloading_game_id = -1
|
||||
elif action == 'cancel':
|
||||
downloader = downloads.get(game_id)
|
||||
if downloader:
|
||||
downloader.cancel_download()
|
||||
elif action == 'resume_seeding':
|
||||
torrent_downloader = TorrentDownloader(torrent_session, lt.torrent_flags.upload_mode)
|
||||
downloads[game_id] = torrent_downloader
|
||||
torrent_downloader.start_download(data['url'], data['save_path'], "")
|
||||
elif action == 'pause_seeding':
|
||||
downloader = downloads.get(game_id)
|
||||
if downloader:
|
||||
downloader.cancel_download()
|
||||
|
||||
else:
|
||||
return jsonify({"error": "Invalid action"}), 400
|
||||
|
||||
return "", 200
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(host="0.0.0.0", port=int(http_port))
|
||||
|
||||
@@ -15,8 +15,8 @@ class ProfileImageProcessor:
|
||||
mime_type = image.get_format_mimetype()
|
||||
return image_path, mime_type
|
||||
else:
|
||||
newUUID = str(uuid.uuid4())
|
||||
new_image_path = os.path.join(tempfile.gettempdir(), newUUID) + ".webp"
|
||||
new_uuid = str(uuid.uuid4())
|
||||
new_image_path = os.path.join(tempfile.gettempdir(), new_uuid) + ".webp"
|
||||
image.save(new_image_path)
|
||||
|
||||
new_image = Image.open(new_image_path)
|
||||
@@ -3,18 +3,18 @@ from cx_Freeze import setup, Executable
|
||||
# Dependencies are automatically detected, but it might need fine tuning.
|
||||
build_exe_options = {
|
||||
"packages": ["libtorrent"],
|
||||
"build_exe": "hydra-download-manager",
|
||||
"build_exe": "hydra-python-rpc",
|
||||
"include_msvcr": True
|
||||
}
|
||||
|
||||
setup(
|
||||
name="hydra-download-manager",
|
||||
name="hydra-python-rpc",
|
||||
version="0.1",
|
||||
description="Hydra",
|
||||
options={"build_exe": build_exe_options},
|
||||
executables=[Executable(
|
||||
"torrent-client/main.py",
|
||||
target_name="hydra-download-manager",
|
||||
"python_rpc/main.py",
|
||||
target_name="hydra-python-rpc",
|
||||
icon="build/icon.ico"
|
||||
)]
|
||||
)
|
||||
@@ -1,10 +1,10 @@
|
||||
import libtorrent as lt
|
||||
|
||||
class TorrentDownloader:
|
||||
def __init__(self, port: str):
|
||||
self.torrent_handles = {}
|
||||
self.downloading_game_id = -1
|
||||
self.session = lt.session({'listen_interfaces': '0.0.0.0:{port}'.format(port=port)})
|
||||
def __init__(self, torrent_session, flags = lt.torrent_flags.auto_managed):
|
||||
self.torrent_handle = None
|
||||
self.session = torrent_session
|
||||
self.flags = flags
|
||||
self.trackers = [
|
||||
"udp://tracker.opentrackr.org:1337/announce",
|
||||
"http://tracker.opentrackr.org:1337/announce",
|
||||
@@ -102,64 +102,48 @@ class TorrentDownloader:
|
||||
"http://bvarf.tracker.sh:2086/announce",
|
||||
]
|
||||
|
||||
def start_download(self, game_id: int, magnet: str, save_path: str):
|
||||
params = {'url': magnet, 'save_path': save_path, 'trackers': self.trackers}
|
||||
torrent_handle = self.session.add_torrent(params)
|
||||
self.torrent_handles[game_id] = torrent_handle
|
||||
torrent_handle.set_flags(lt.torrent_flags.auto_managed)
|
||||
torrent_handle.resume()
|
||||
def start_download(self, magnet: str, save_path: str, header: str):
|
||||
params = {'url': magnet, 'save_path': save_path, 'trackers': self.trackers, 'flags': self.flags}
|
||||
self.torrent_handle = self.session.add_torrent(params)
|
||||
self.torrent_handle.resume()
|
||||
|
||||
self.downloading_game_id = game_id
|
||||
def pause_download(self):
|
||||
if self.torrent_handle:
|
||||
self.torrent_handle.pause()
|
||||
self.torrent_handle.unset_flags(lt.torrent_flags.auto_managed)
|
||||
|
||||
def pause_download(self, game_id: int):
|
||||
torrent_handle = self.torrent_handles.get(game_id)
|
||||
if torrent_handle:
|
||||
torrent_handle.pause()
|
||||
torrent_handle.unset_flags(lt.torrent_flags.auto_managed)
|
||||
self.downloading_game_id = -1
|
||||
|
||||
def cancel_download(self, game_id: int):
|
||||
torrent_handle = self.torrent_handles.get(game_id)
|
||||
if torrent_handle:
|
||||
torrent_handle.pause()
|
||||
self.session.remove_torrent(torrent_handle)
|
||||
self.torrent_handles[game_id] = None
|
||||
self.downloading_game_id = -1
|
||||
def cancel_download(self):
|
||||
if self.torrent_handle:
|
||||
self.torrent_handle.pause()
|
||||
self.session.remove_torrent(self.torrent_handle)
|
||||
self.torrent_handle = None
|
||||
|
||||
def abort_session(self):
|
||||
for game_id in self.torrent_handles:
|
||||
torrent_handle = self.torrent_handles[game_id]
|
||||
torrent_handle.pause()
|
||||
self.session.remove_torrent(torrent_handle)
|
||||
self.torrent_handle = self.torrent_handles[game_id]
|
||||
self.torrent_handle.pause()
|
||||
self.session.remove_torrent(self.torrent_handle)
|
||||
|
||||
self.session.abort()
|
||||
self.torrent_handles = {}
|
||||
self.downloading_game_id = -1
|
||||
self.torrent_handle = None
|
||||
|
||||
def get_download_status(self):
|
||||
if self.downloading_game_id == -1:
|
||||
if self.torrent_handle is None:
|
||||
return None
|
||||
|
||||
torrent_handle = self.torrent_handles.get(self.downloading_game_id)
|
||||
|
||||
status = torrent_handle.status()
|
||||
info = torrent_handle.get_torrent_info()
|
||||
status = self.torrent_handle.status()
|
||||
info = self.torrent_handle.get_torrent_info()
|
||||
|
||||
response = {
|
||||
'folderName': info.name() if info else "",
|
||||
'fileSize': info.total_size() if info else 0,
|
||||
'gameId': self.downloading_game_id,
|
||||
'progress': status.progress,
|
||||
'downloadSpeed': status.download_rate,
|
||||
'uploadSpeed': status.upload_rate,
|
||||
'numPeers': status.num_peers,
|
||||
'numSeeds': status.num_seeds,
|
||||
'status': status.state,
|
||||
'bytesDownloaded': status.progress * info.total_size() if info else status.all_time_download,
|
||||
}
|
||||
|
||||
if status.progress == 1:
|
||||
torrent_handle.pause()
|
||||
self.session.remove_torrent(torrent_handle)
|
||||
self.downloading_game_id = -1
|
||||
|
||||
return response
|
||||
@@ -1,6 +1,8 @@
|
||||
libtorrent
|
||||
cx_Freeze
|
||||
cx_Freeze == 7.2.3
|
||||
cx_Logging; sys_platform == 'win32'
|
||||
pywin32; sys_platform == 'win32'
|
||||
psutil
|
||||
Pillow
|
||||
flask
|
||||
aria2p
|
||||
|
||||
|
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 18 KiB |
120
scripts/postinstall.cjs
Normal file
@@ -0,0 +1,120 @@
|
||||
const { default: axios } = require("axios");
|
||||
const util = require("node:util");
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
const { spawnSync } = require("node:child_process");
|
||||
|
||||
const exec = util.promisify(require("node:child_process").exec);
|
||||
|
||||
const fileName = {
|
||||
win32: "ludusavi-v0.25.0-win64.zip",
|
||||
linux: "ludusavi-v0.25.0-linux.zip",
|
||||
darwin: "ludusavi-v0.25.0-mac.zip",
|
||||
};
|
||||
|
||||
const downloadLudusavi = async () => {
|
||||
if (fs.existsSync("ludusavi")) {
|
||||
console.log("Ludusavi already exists, skipping download...");
|
||||
return;
|
||||
}
|
||||
|
||||
const file = fileName[process.platform];
|
||||
const downloadUrl = `https://github.com/mtkennerly/ludusavi/releases/download/v0.25.0/${file}`;
|
||||
|
||||
console.log(`Downloading ${file}...`);
|
||||
|
||||
const response = await axios.get(downloadUrl, { responseType: "stream" });
|
||||
|
||||
const stream = response.data.pipe(fs.createWriteStream(file));
|
||||
|
||||
stream.on("finish", async () => {
|
||||
console.log(`Downloaded ${file}, extracting...`);
|
||||
|
||||
const pwd = process.cwd();
|
||||
|
||||
const targetPath = path.join(pwd, "ludusavi");
|
||||
|
||||
await exec(`npx extract-zip ${file} ${targetPath}`);
|
||||
|
||||
if (process.platform !== "win32") {
|
||||
fs.chmodSync(path.join(targetPath, "ludusavi"), 0o755);
|
||||
}
|
||||
|
||||
console.log("Extracted. Renaming folder...");
|
||||
|
||||
console.log(`Extracted ${file}, removing compressed downloaded file...`);
|
||||
fs.rmSync(file);
|
||||
});
|
||||
};
|
||||
|
||||
const downloadAria2WindowsAndLinux = async () => {
|
||||
if (fs.existsSync("aria2")) {
|
||||
console.log("Aria2 already exists, skipping download...");
|
||||
return;
|
||||
}
|
||||
|
||||
const file =
|
||||
process.platform === "win32"
|
||||
? "aria2-1.37.0-win-64bit-build1.zip"
|
||||
: "aria2-1.37.0-1-x86_64.pkg.tar.zst";
|
||||
|
||||
const downloadUrl =
|
||||
process.platform === "win32"
|
||||
? `https://github.com/aria2/aria2/releases/download/release-1.37.0/${file}`
|
||||
: "https://archlinux.org/packages/extra/x86_64/aria2/download/";
|
||||
|
||||
console.log(`Downloading ${file}...`);
|
||||
|
||||
const response = await axios.get(downloadUrl, { responseType: "stream" });
|
||||
|
||||
const stream = response.data.pipe(fs.createWriteStream(file));
|
||||
|
||||
stream.on("finish", async () => {
|
||||
console.log(`Downloaded ${file}, extracting...`);
|
||||
|
||||
if (process.platform === "win32") {
|
||||
await exec(`npx extract-zip ${file}`);
|
||||
console.log("Extracted. Renaming folder...");
|
||||
|
||||
fs.mkdirSync("aria2");
|
||||
fs.copyFileSync(
|
||||
path.join(file.replace(".zip", ""), "aria2c.exe"),
|
||||
"aria2/aria2c.exe"
|
||||
);
|
||||
fs.rmSync(file.replace(".zip", ""), { recursive: true });
|
||||
} else {
|
||||
await exec(`tar --zstd -xvf ${file} usr/bin/aria2c`);
|
||||
console.log("Extracted. Copying binary file...");
|
||||
fs.mkdirSync("aria2");
|
||||
fs.copyFileSync("usr/bin/aria2c", "aria2/aria2c");
|
||||
fs.rmSync("usr", { recursive: true });
|
||||
}
|
||||
|
||||
console.log(`Extracted ${file}, removing compressed downloaded file...`);
|
||||
fs.rmSync(file);
|
||||
});
|
||||
};
|
||||
|
||||
const copyAria2Macos = async () => {
|
||||
console.log("Checking if aria2 is installed...");
|
||||
|
||||
const isAria2Installed = spawnSync("which", ["aria2c"]).status;
|
||||
|
||||
if (isAria2Installed != 0) {
|
||||
console.log("Please install aria2");
|
||||
console.log("brew install aria2");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("Copying aria2 binary...");
|
||||
fs.mkdirSync("aria2");
|
||||
await exec(`cp $(which aria2c) aria2/aria2c`);
|
||||
};
|
||||
|
||||
if (process.platform == "darwin") {
|
||||
copyAria2Macos();
|
||||
} else {
|
||||
downloadAria2WindowsAndLinux();
|
||||
}
|
||||
|
||||
downloadLudusavi();
|
||||
66
scripts/upload-build.cjs
Normal file
@@ -0,0 +1,66 @@
|
||||
const fs = require("node:fs");
|
||||
const { S3Client, PutObjectCommand } = require("@aws-sdk/client-s3");
|
||||
const path = require("node:path");
|
||||
const packageJson = require("../package.json");
|
||||
|
||||
if (!process.env.BUILD_WEBHOOK_URL) {
|
||||
console.log("No BUILD_WEBHOOK_URL provided, skipping upload");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const s3 = new S3Client({
|
||||
region: "auto",
|
||||
endpoint: process.env.S3_ENDPOINT,
|
||||
forcePathStyle: true,
|
||||
credentials: {
|
||||
accessKeyId: process.env.S3_ACCESS_KEY_ID,
|
||||
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
|
||||
},
|
||||
});
|
||||
|
||||
const dist = path.resolve(__dirname, "..", "dist");
|
||||
|
||||
const extensionsToUpload = [".deb", ".exe", ".pacman"];
|
||||
|
||||
fs.readdir(dist, async (err, files) => {
|
||||
if (err) throw err;
|
||||
|
||||
const uploads = await Promise.all(
|
||||
files
|
||||
.filter((file) => extensionsToUpload.includes(path.extname(file)))
|
||||
.map(async (file) => {
|
||||
console.log(`⌛️ Uploading ${file}...`);
|
||||
const fileName = `${new Date().getTime()}-${file}`;
|
||||
|
||||
const command = new PutObjectCommand({
|
||||
Bucket: process.env.S3_BUILDS_BUCKET_NAME,
|
||||
Key: fileName,
|
||||
Body: fs.createReadStream(path.resolve(dist, file)),
|
||||
// 3 days
|
||||
Expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 3),
|
||||
});
|
||||
|
||||
await s3.send(command);
|
||||
|
||||
return {
|
||||
url: `${process.env.BUILDS_URL}/${fileName}`,
|
||||
name: fileName,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
if (uploads.length > 0) {
|
||||
await fetch(process.env.BUILD_WEBHOOK_URL, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
uploads,
|
||||
branchName: process.env.BRANCH_NAME,
|
||||
version: packageJson.version,
|
||||
githubActor: process.env.GITHUB_ACTOR,
|
||||
}),
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1,33 +1,49 @@
|
||||
{
|
||||
"language_name": "اَلْعَرَبِيَّةُ",
|
||||
"app": {
|
||||
"successfully_signed_in": "تم تسجيل الدخول بنجاح"
|
||||
},
|
||||
"home": {
|
||||
"featured": "مميّز",
|
||||
"surprise_me": "فاجئني",
|
||||
"no_results": "لم يتم العثور على نتائج"
|
||||
"no_results": "لم يتم العثور على نتائج",
|
||||
"start_typing": "بدء الكتابة للبحث...",
|
||||
"hot": "الأكثر رواجا الآن",
|
||||
"weekly": "📅 أفضل ألعاب الأسبوع",
|
||||
"achievements": "🏆 ألعاب للتغلب عليها"
|
||||
},
|
||||
"sidebar": {
|
||||
"catalogue": "قائمة الألعاب",
|
||||
"downloads": "التحميلات",
|
||||
"downloads": "التنزيلات",
|
||||
"settings": "إعدادات",
|
||||
"my_library": "مكتبتي",
|
||||
"downloading_metadata": "{{title}} (جارٍ تنزيل البيانات الوصفية...)",
|
||||
"paused": "{{title}} (متوقف)",
|
||||
"downloading": "{{title}} ({{percentage}} - جارٍ التنزيل...)",
|
||||
"paused": "{{title}} (متوقف مؤقتًا)",
|
||||
"downloading": "{{title}} ({{percentage}} - جاري التنزيل...)",
|
||||
"filter": "بحث في المكتبة",
|
||||
"home": "الرئيسية"
|
||||
"home": "الرئيسية",
|
||||
"queued": "{{title}} (في قائمة الانتظار)",
|
||||
"game_has_no_executable": "لم يتم تحديد اللعبة القابلة للتنفيذ",
|
||||
"sign_in": "تسجيل الدخول",
|
||||
"friends": "أصدقاء",
|
||||
"need_help": "بحاجة الى مساعدة؟"
|
||||
},
|
||||
"header": {
|
||||
"search": "ابحث عن الألعاب",
|
||||
"home": "الرئيسية",
|
||||
"catalogue": "قائمة الألعاب",
|
||||
"downloads": "التحميلات",
|
||||
"downloads": "التنزيلات",
|
||||
"search_results": "نتائج البحث",
|
||||
"settings": "إعدادات"
|
||||
"settings": "إعدادات",
|
||||
"version_available_install": "إصدار {{version}} متاح. ",
|
||||
"version_available_download": "إصدار {{version}} متاح. "
|
||||
},
|
||||
"bottom_panel": {
|
||||
"no_downloads_in_progress": "لا يوجد تنزيلات جارية",
|
||||
"downloading_metadata": "جارٍ تنزيل بيانات وصف {{title}}",
|
||||
"downloading": "جارٍ تنزيل {{title}}… ({{percentage}} مكتملة) - الانتهاء {{eta}} - {{speed}}"
|
||||
"no_downloads_in_progress": "لا توجد تنزيلات قيد التقدم",
|
||||
"downloading_metadata": "جارٍ التنزيل {{title}} البيانات الوصفية...",
|
||||
"downloading": "جارٍ التنزيل {{title}}… ({{percentage}} مكتملة) - الانتهاء {{eta}} - {{speed}}",
|
||||
"calculating_eta": "جارٍ التنزيل {{title}}… ({{percentage}} مكتمل) - حساب الوقت المتبقي...",
|
||||
"checking_files": "التحقق {{title}} ملفات…({{percentage}} مكتمل)"
|
||||
},
|
||||
"catalogue": {
|
||||
"next_page": "الصفحة التالية",
|
||||
@@ -35,101 +51,242 @@
|
||||
},
|
||||
"game_details": {
|
||||
"open_download_options": "افتح خيارات التنزيل",
|
||||
"download_options_zero": "لا يوجد خيار تنزيل",
|
||||
"download_options_one": "{{count}} خيار تنزيل",
|
||||
"download_options_other": "{{count}} خيار تنزيل",
|
||||
"download_options_zero": "{{count}} خيارات التنزيل",
|
||||
"updated_at": "تم التحديث {{updated_at}}",
|
||||
"install": "تثبيت",
|
||||
"install": "ثَبَّتَ",
|
||||
"resume": "استئناف",
|
||||
"pause": "إيقاف",
|
||||
"cancel": "إلغاء",
|
||||
"remove": "إزالة",
|
||||
"space_left_on_disk": "{{space}} متبقية على القرص",
|
||||
"eta": "الوقت المتبقي {{eta}}",
|
||||
"downloading_metadata": "جاري تنزيل البيانات الوصفية...",
|
||||
"filter": "تصفية حزم إعادة التجميع",
|
||||
"calculating_eta": "جارٍ حساب الوقت المتبقي…",
|
||||
"downloading_metadata": "جارٍ تنزيل البيانات الوصفية…",
|
||||
"filter": "إعادة حزم التصفية",
|
||||
"requirements": "متطلبات النظام",
|
||||
"minimum": "الحد الأدنى",
|
||||
"recommended": "موصى به",
|
||||
"release_date": "تم الإصدار في {{date}}",
|
||||
"publisher": "نشر بواسطة {{publisher}}",
|
||||
"recommended": "مُستَحسَن",
|
||||
"paused": "متوقف مؤقتًا",
|
||||
"release_date": "صدر بتاريخ {{date}}",
|
||||
"publisher": "نشرت من قبل {{publisher}}",
|
||||
"hours": "ساعات",
|
||||
"minutes": "دقائق",
|
||||
"amount_hours": "{{amount}} ساعات",
|
||||
"amount_minutes": "{{amount}} دقائق",
|
||||
"accuracy": "دقة {{accuracy}}%",
|
||||
"add_to_library": "إضافة إلى المكتبة",
|
||||
"accuracy": "{{accuracy}}٪ دقة",
|
||||
"add_to_library": "أضف إلى المكتبة",
|
||||
"remove_from_library": "إزالة من المكتبة",
|
||||
"no_downloads": "لا توجد تنزيلات متاحة",
|
||||
"no_downloads": "لا التنزيلات المتاحة",
|
||||
"play_time": "تم اللعب لمدة {{amount}}",
|
||||
"last_time_played": "آخر مرة لعبت {{period}}",
|
||||
"not_played_yet": "لم تلعب {{title}} بعد",
|
||||
"last_time_played": "لعبت آخر مرة {{period}}",
|
||||
"not_played_yet": "أنت لم تلعب {{title}} حتى الآن",
|
||||
"next_suggestion": "الاقتراح التالي",
|
||||
"play": "لعب",
|
||||
"deleting": "جاري حذف المثبت...",
|
||||
"deleting": "جارٍ حذف المثبت…",
|
||||
"close": "إغلاق",
|
||||
"playing_now": "قيد التشغيل الآن",
|
||||
"playing_now": "قيداللعب الآن",
|
||||
"change": "تغيير",
|
||||
"repacks_modal_description": "اختر الحزمة التي تريد تنزيلها",
|
||||
"select_folder_hint": "لتغيير المجلد الافتراضي، انتقل إلى الإعدادات",
|
||||
"download_now": "تنزيل الآن",
|
||||
"no_shop_details": "لم يتم استرداد تفاصيل المتجر.",
|
||||
"select_folder_hint": "لتغيير المجلد الافتراضي، انتقل إلى <0>إعدادات</0>",
|
||||
"download_now": "قم بالتنزيل الآن",
|
||||
"no_shop_details": "لا يمكن استرداد تفاصيل المتجر.",
|
||||
"download_options": "خيارات التنزيل",
|
||||
"download_path": "مسار التنزيل",
|
||||
"download_path": "مسار التحميل",
|
||||
"previous_screenshot": "لقطة الشاشة السابقة",
|
||||
"next_screenshot": "لقطة الشاشة التالية",
|
||||
"screenshot": "لقطة شاشة {{number}}",
|
||||
"open_screenshot": "افتح لقطة الشاشة {{number}}"
|
||||
"screenshot": "لقطة الشاشة {{number}}",
|
||||
"open_screenshot": "فتح لقطة الشاشة {{number}}",
|
||||
"download_settings": "تحميل الإعدادات",
|
||||
"downloader": "أداة التنزيل",
|
||||
"select_executable": "يختار",
|
||||
"no_executable_selected": "لم يتم تحديد أي ملف قابل للتنفيذ",
|
||||
"open_folder": "افتح المجلد",
|
||||
"open_download_location": "انظر الملفات التي تم تنزيلها",
|
||||
"create_shortcut": "إنشاء اختصار سطح المكتب",
|
||||
"clear": "واضح",
|
||||
"remove_files": "إزالة الملفات",
|
||||
"remove_from_library_title": "هل أنت متأكد؟",
|
||||
"remove_from_library_description": "سيتم إزالة هذا {{game}} من مكتبتك",
|
||||
"options": "خيارات",
|
||||
"executable_section_title": "قابل للتنفيذ",
|
||||
"executable_section_description": "مسار الملف الذي سيتم تنفيذه عند النقر فوق \"تشغيل\".",
|
||||
"downloads_secion_title": "التنزيلات",
|
||||
"downloads_section_description": "تحقق من التحديثات أو الإصدارات الأخرى من هذه اللعبة",
|
||||
"danger_zone_section_title": "منطقة الخطر",
|
||||
"danger_zone_section_description": "قم بإزالة هذه اللعبة من مكتبتك أو الملفات التي تم تنزيلها بواسطة Hydra",
|
||||
"download_in_progress": "التنزيل قيد التقدم",
|
||||
"download_paused": "تم إيقاف التنزيل مؤقتًا",
|
||||
"last_downloaded_option": "آخر خيار تم تنزيله",
|
||||
"create_shortcut_success": "تم إنشاء الاختصار بنجاح",
|
||||
"create_shortcut_error": "حدث خطأ أثناء إنشاء الاختصار",
|
||||
"nsfw_content_title": "تحتوي هذه اللعبة على محتوى غير مناسب",
|
||||
"nsfw_content_description": "{{title}} يحتوي على محتوى قد لا يكون مناسبًا لجميع الأعمار. ",
|
||||
"allow_nsfw_content": "اسمح",
|
||||
"refuse_nsfw_content": "عُد",
|
||||
"stats": "احصائيات",
|
||||
"download_count": "التنزيلات",
|
||||
"player_count": "اللاعبين النشطين",
|
||||
"download_error": "خيار التنزيل هذا غير متوفر",
|
||||
"download": "تحميل",
|
||||
"executable_path_in_use": "قابل للتنفيذ قيد الاستخدام بالفعل بواسطة \"{{game}}\"",
|
||||
"warning": "تحذير:",
|
||||
"hydra_needs_to_remain_open": "لإجراء هذا التنزيل، يجب أن يظل Hydra مفتوحًا حتى اكتماله. ",
|
||||
"achievements": "الإنجازات",
|
||||
"achievements_count": "الإنجازات {{unlockedCount}}/{{achievementsCount}}",
|
||||
"cloud_save": "حفظ السحابة",
|
||||
"cloud_save_description": "احفظ تقدمك في السحابة واستمر في اللعب على أي جهاز",
|
||||
"backups": "النسخ الاحتياطية",
|
||||
"install_backup": "ثَبَّتَ",
|
||||
"delete_backup": "يمسح",
|
||||
"create_backup": "نسخة احتياطية جديدة",
|
||||
"last_backup_date": "آخر نسخة احتياطية قيد التشغيل {{date}}",
|
||||
"no_backup_preview": "لم يتم العثور على ألعاب محفوظة لهذا العنوان",
|
||||
"restoring_backup": "استعادة النسخة الاحتياطية ({{progress}} مكتمل)…",
|
||||
"uploading_backup": "جارٍ تحميل النسخة الاحتياطية…",
|
||||
"no_backups": "لم تقم بإنشاء أي نسخ احتياطية لهذه اللعبة حتى الآن",
|
||||
"backup_uploaded": "تم تحميل النسخة الاحتياطية",
|
||||
"backup_deleted": "تم حذف النسخة الاحتياطية",
|
||||
"backup_restored": "تمت استعادة النسخة الاحتياطية",
|
||||
"see_all_achievements": "شاهد جميع الإنجازات",
|
||||
"sign_in_to_see_achievements": "قم بتسجيل الدخول لرؤية الإنجازات",
|
||||
"mapping_method_automatic": "تلقائي",
|
||||
"mapping_method_manual": "يدوي",
|
||||
"mapping_method_label": "طريقة رسم الخرائط",
|
||||
"files_automatically_mapped": "تم تعيين الملفات تلقائيًا",
|
||||
"no_backups_created": "لم يتم إنشاء نسخ احتياطية لهذه اللعبة",
|
||||
"manage_files": "إدارة الملفات",
|
||||
"loading_save_preview": "جارٍ البحث عن حفظ الألعاب...",
|
||||
"wine_prefix": "بادئة النبيذ",
|
||||
"wine_prefix_description": "بادئة Wine المستخدمة لتشغيل هذه اللعبة",
|
||||
"no_download_option_info": "لا توجد معلومات متاحة",
|
||||
"backup_deletion_failed": "فشل في حذف النسخة الاحتياطية",
|
||||
"max_number_of_artifacts_reached": "تم الوصول إلى الحد الأقصى لعدد النسخ الاحتياطية لهذه اللعبة",
|
||||
"achievements_not_sync": "لا تتم مزامنة إنجازاتك",
|
||||
"manage_files_description": "إدارة الملفات التي سيتم نسخها احتياطيًا واستعادتها",
|
||||
"select_folder": "حدد المجلد",
|
||||
"backup_from": "نسخة احتياطية من {{date}}",
|
||||
"custom_backup_location_set": "تعيين موقع النسخ الاحتياطي المخصص",
|
||||
"no_directory_selected": "لم يتم تحديد أي دليل",
|
||||
"download_options_one": "{{count}} خيار التنزيل",
|
||||
"download_options_two": "{{count}} خيارات التنزيل",
|
||||
"download_options_few": "{{count}} خيارات التنزيل",
|
||||
"download_options_many": "{{count}} خيارات التنزيل",
|
||||
"download_options_other": "{{count}} خيارات التنزيل"
|
||||
},
|
||||
"activation": {
|
||||
"title": "تفعيل هايدرا",
|
||||
"title": "تفعيل Hydra",
|
||||
"installation_id": "معرف التثبيت:",
|
||||
"enter_activation_code": "أدخل رمز التفعيل الخاص بك",
|
||||
"message": "إذا كنت لا تعرف أين تسأل عن هذا ، فلا يجب أن يكون لديك هذا.",
|
||||
"activate": "تفعيل",
|
||||
"loading": "جار التحميل…"
|
||||
"message": "إذا كنت لا تعرف أين تطلب هذا، فلا ينبغي أن يكون لديك هذا.",
|
||||
"activate": "فعل",
|
||||
"loading": "تحميل…"
|
||||
},
|
||||
"downloads": {
|
||||
"resume": "استئناف",
|
||||
"pause": "إيقاف مؤقت",
|
||||
"eta": "الوقت المتبقي {{eta}}",
|
||||
"paused": "متوقفة مؤقتًا",
|
||||
"verifying": "جار التحقق…",
|
||||
"completed": "اكتمل",
|
||||
"paused": "متوقف مؤقتًا",
|
||||
"verifying": "جارٍ التحقق…",
|
||||
"completed": "مكتمل",
|
||||
"removed": "لم يتم تحميلها",
|
||||
"cancel": "إلغاء",
|
||||
"filter": "تصفية الألعاب التي تم تنزيلها",
|
||||
"remove": "إزالة",
|
||||
"downloading_metadata": "جار تنزيل البيانات الوصفية…",
|
||||
"deleting": "جار حذف المثبت…",
|
||||
"downloading_metadata": "جارٍ تنزيل البيانات الوصفية…",
|
||||
"deleting": "جارٍ حذف المثبت…",
|
||||
"delete": "إزالة المثبت",
|
||||
"delete_modal_title": "هل أنت متأكد؟",
|
||||
"delete_modal_description": "سيؤدي هذا إلى إزالة جميع ملفات التثبيت من جهاز الكمبيوتر الخاص بك",
|
||||
"install": "تثبيت"
|
||||
"delete_modal_description": "سيؤدي هذا إلى إزالة كافة ملفات التثبيت من جهاز الكمبيوتر الخاص بك",
|
||||
"install": "ثَبَّتَ",
|
||||
"download_in_progress": "في تَقَدم",
|
||||
"queued_downloads": "التنزيلات في قائمة الانتظار",
|
||||
"downloads_completed": "مكتمل",
|
||||
"queued": "في قائمة الانتظار",
|
||||
"no_downloads_title": "هذا فارغ",
|
||||
"no_downloads_description": "لم تقم بتنزيل أي شيء باستخدام Hydra بعد، ولكن لم يفت الأوان بعد للبدء.",
|
||||
"checking_files": "جارٍ فحص الملفات…"
|
||||
},
|
||||
"settings": {
|
||||
"downloads_path": "مسار التنزيلات",
|
||||
"change": "تحديث",
|
||||
"notifications": "الإشعارات",
|
||||
"notifications": "إشعارات",
|
||||
"enable_download_notifications": "عند اكتمال التنزيل",
|
||||
"enable_repack_list_notifications": "عند إضافة حزمة جديدة",
|
||||
"real_debrid_api_token_label": "رمز واجهة برمجة التطبيقات (API) لـReal-Debrid ",
|
||||
"quit_app_instead_hiding": "إنهاء هايدرا بدلاً من التصغير الى شريط الحالة",
|
||||
"launch_with_system": "تشغيل هايدرا عند بدء تشغيل النظام",
|
||||
"real_debrid_api_token_label": "رمز Real-Debrid API",
|
||||
"quit_app_instead_hiding": "لا تخفي Hydra عند الإغلاق",
|
||||
"launch_with_system": "قم بتشغيل Hydra عند بدء تشغيل النظام",
|
||||
"general": "عام",
|
||||
"behavior": "السلوك",
|
||||
"enable_real_debrid": "تفعيل Real-Debrid ",
|
||||
"real_debrid_api_token_hint": "يمكنك الحصول على مفتاح API الخاص بك هنا",
|
||||
"save_changes": "حفظ التغييرات"
|
||||
"behavior": "سلوك",
|
||||
"download_sources": "تحميل المصادر",
|
||||
"language": "لغة",
|
||||
"real_debrid_api_token": "رمز API",
|
||||
"enable_real_debrid": "تمكين ريال ديبريد",
|
||||
"real_debrid_description": "Real-Debrid هو برنامج تنزيل غير مقيد يسمح لك بتنزيل الملفات بسرعة، ولا يقتصر ذلك إلا على سرعة الإنترنت لديك.",
|
||||
"real_debrid_invalid_token": "رمز API غير صالح",
|
||||
"real_debrid_api_token_hint": "يمكنك الحصول على رمز API الخاص بك <0>هنا</0>",
|
||||
"real_debrid_free_account_error": "الحساب \"{{username}}\" هو حساب مجاني. يرجى الاشتراك في Real-Debrid",
|
||||
"real_debrid_linked_message": "حساب \"{{username}}\"مرتبط",
|
||||
"save_changes": "حفظ التغييرات",
|
||||
"changes_saved": "تم حفظ التغييرات بنجاح",
|
||||
"download_sources_description": "ستقوم Hydra بجلب روابط التنزيل من هذه المصادر. ",
|
||||
"validate_download_source": "التحقق من صحة",
|
||||
"remove_download_source": "إزالة",
|
||||
"add_download_source": "أضف المصدر",
|
||||
"download_count_zero": "{{countFormatted}} خيارات التنزيل",
|
||||
"download_source_url": "تنزيل عنوان URL المصدر",
|
||||
"add_download_source_description": "أدخل عنوان URL لملف .json",
|
||||
"download_source_up_to_date": "محدث",
|
||||
"download_source_errored": "خطأ",
|
||||
"sync_download_sources": "مصادر المزامنة",
|
||||
"removed_download_source": "تمت إزالة مصدر التنزيل",
|
||||
"added_download_source": "تمت إضافة مصدر التنزيل",
|
||||
"download_sources_synced": "تتم مزامنة جميع مصادر التنزيل",
|
||||
"insert_valid_json_url": "أدخل عنوان URL صالحًا لـ JSON",
|
||||
"found_download_option_zero": "وجد {{countFormatted}} خيارات التنزيل",
|
||||
"import": "يستورد",
|
||||
"public": "عام",
|
||||
"private": "خاص",
|
||||
"friends_only": "الأصدقاء فقط",
|
||||
"privacy": "خصوصية",
|
||||
"profile_visibility": "رؤية الملف الشخصي",
|
||||
"profile_visibility_description": "اختر من يمكنه رؤية ملفك الشخصي ومكتبتك",
|
||||
"required_field": "هذه الخانة مطلوبه",
|
||||
"source_already_exists": "تمت إضافة هذا المصدر بالفعل",
|
||||
"must_be_valid_url": "يجب أن يكون المصدر عنوان URL صالحًا",
|
||||
"blocked_users": "المستخدمين المحظورين",
|
||||
"user_unblocked": "تم إلغاء حظر المستخدم",
|
||||
"enable_achievement_notifications": "عندما يتم فتح الإنجاز",
|
||||
"launch_minimized": "تم تصغير إطلاق Hydra",
|
||||
"disable_nsfw_alert": "تعطيل تنبيه NSFW",
|
||||
"show_hidden_achievement_description": "إظهار وصف الإنجازات المخفية قبل فتحها",
|
||||
"download_count_one": "{{countFormatted}} خيار التنزيل",
|
||||
"download_count_two": "{{countFormatted}} خيارات التنزيل",
|
||||
"download_count_few": "{{countFormatted}} خيارات التنزيل",
|
||||
"download_count_many": "{{countFormatted}} خيارات التنزيل",
|
||||
"download_count_other": "{{countFormatted}} خيارات التنزيل",
|
||||
"found_download_option_one": "وجد {{countFormatted}} خيار التنزيل",
|
||||
"found_download_option_two": "وجد {{countFormatted}} خيارات التنزيل",
|
||||
"found_download_option_few": "وجد {{countFormatted}} خيارات التنزيل",
|
||||
"found_download_option_many": "وجد {{countFormatted}} خيارات التنزيل",
|
||||
"found_download_option_other": "وجد {{countFormatted}} خيارات التنزيل"
|
||||
},
|
||||
"notifications": {
|
||||
"download_complete": "تم التحميل",
|
||||
"game_ready_to_install": "{{title}} جاهزة للتثبيت",
|
||||
"repack_list_updated": "قائمة التجميعات المحدثة",
|
||||
"repack_count_one": "{{count}} حزمة مضافة",
|
||||
"repack_count_other": "{{count}} حزم مُضافة"
|
||||
"download_complete": "اكتمل التنزيل",
|
||||
"game_ready_to_install": "{{title}} جاهز للتثبيت",
|
||||
"repack_list_updated": "تم تحديث قائمة إعادة التعبئة",
|
||||
"new_update_available": "إصدار {{version}} متاح",
|
||||
"restart_to_install_update": "أعد تشغيل Hydra لتثبيت التحديث",
|
||||
"notification_achievement_unlocked_title": "تم فتح الإنجاز لـ {{game}}",
|
||||
"notification_achievement_unlocked_body": "{{achievement}} وغيرها {{count}} تم فتحها",
|
||||
"repack_count_zero": "{{count}} تمت إضافة العبوات",
|
||||
"repack_count_one": "{{count}} تمت إضافة أعد حزم",
|
||||
"repack_count_two": "{{count}} تمت إضافة العبوات",
|
||||
"repack_count_few": "{{count}} تمت إضافة العبوات",
|
||||
"repack_count_many": "{{count}} تمت إضافة العبوات",
|
||||
"repack_count_other": "{{count}} تمت إضافة العبوات"
|
||||
},
|
||||
"system_tray": {
|
||||
"open": "فتح هايدرا",
|
||||
"open": "افتح Hydra",
|
||||
"quit": "خروج"
|
||||
},
|
||||
"game_card": {
|
||||
@@ -137,10 +294,109 @@
|
||||
},
|
||||
"binary_not_found_modal": {
|
||||
"title": "البرامج غير مثبتة",
|
||||
"description": "لم يتم العثور على ملفات Wine أو Lutris التنفيذية على نظامك",
|
||||
"instructions": "تحقق من الطريقة الصحيحة لتثبيت أي منها على توزيعة Linux الخاصة بك حتى تعمل اللعبة بشكل طبيعي"
|
||||
"description": "لم يتم العثور على الملفات التنفيذية الخاصة بـ Wine أو Lutris على نظامك",
|
||||
"instructions": "تحقق من الطريقة الصحيحة لتثبيت أي منها على توزيعة Linux لديك حتى تعمل اللعبة بشكل طبيعي"
|
||||
},
|
||||
"modal": {
|
||||
"close": "زر إغلاق"
|
||||
"close": "زر الإغلاق"
|
||||
},
|
||||
"forms": {
|
||||
"toggle_password_visibility": "تبديل رؤية كلمة المرور"
|
||||
},
|
||||
"user_profile": {
|
||||
"amount_hours": "{{amount}} ساعات",
|
||||
"amount_minutes": "{{amount}} دقائق",
|
||||
"last_time_played": "لعبت آخر مرة {{period}}",
|
||||
"activity": "النشاط الأخير",
|
||||
"library": "مكتبة",
|
||||
"total_play_time": "إجمالي وقت اللعب",
|
||||
"no_recent_activity_title": "هممم... لا شيء هنا",
|
||||
"no_recent_activity_description": "لم تلعب أي مباراة مؤخرًا. ",
|
||||
"display_name": "اسم العرض",
|
||||
"saving": "توفير",
|
||||
"save": "يحفظ",
|
||||
"edit_profile": "تحرير الملف الشخصي",
|
||||
"saved_successfully": "تم الحفظ بنجاح",
|
||||
"try_again": "من فضلك، حاول مرة أخرى",
|
||||
"sign_out_modal_title": "هل أنت متأكد؟",
|
||||
"cancel": "إلغاء",
|
||||
"successfully_signed_out": "تم تسجيل الخروج بنجاح",
|
||||
"sign_out": "تسجيل الخروج",
|
||||
"playing_for": "اللعب من أجل {{amount}}",
|
||||
"sign_out_modal_text": "مكتبتك مرتبطة بحسابك الحالي. ",
|
||||
"add_friends": "أضف أصدقاء",
|
||||
"add": "يضيف",
|
||||
"friend_code": "رمز الصديق",
|
||||
"see_profile": "انظر الملف الشخصي",
|
||||
"sending": "إرسال",
|
||||
"friend_request_sent": "تم إرسال طلب الصداقة",
|
||||
"friends": "أصدقاء",
|
||||
"friends_list": "قائمة الأصدقاء",
|
||||
"user_not_found": "لم يتم العثور على المستخدم",
|
||||
"block_user": "حظر المستخدم",
|
||||
"add_friend": "إضافة صديق",
|
||||
"request_sent": "تم إرسال الطلب",
|
||||
"request_received": "تم استلام الطلب",
|
||||
"accept_request": "قبول الطلب",
|
||||
"ignore_request": "تجاهل الطلب",
|
||||
"cancel_request": "إلغاء الطلب",
|
||||
"undo_friendship": "التراجع عن الصداقة",
|
||||
"request_accepted": "تم قبول الطلب",
|
||||
"user_blocked_successfully": "تم حظر المستخدم بنجاح",
|
||||
"user_block_modal_text": "هذا سوف يمنع {{displayName}}",
|
||||
"blocked_users": "المستخدمين المحظورين",
|
||||
"unblock": "إلغاء الحظر",
|
||||
"no_friends_added": "ليس لديك أي أصدقاء مضافين",
|
||||
"pending": "قيد الانتظار",
|
||||
"no_pending_invites": "ليس لديك أي دعوات معلقة",
|
||||
"no_blocked_users": "ليس لديك أي مستخدمين محظورين",
|
||||
"friend_code_copied": "تم نسخ رمز الصديق",
|
||||
"undo_friendship_modal_text": "سيؤدي هذا إلى التراجع عن صداقتك معه {{displayName}}",
|
||||
"privacy_hint": "لضبط من يمكنه رؤية هذا، انتقل إلى <0>إعدادات</0>",
|
||||
"locked_profile": "هذا الملف الشخصي خاص",
|
||||
"image_process_failure": "فشل أثناء معالجة الصورة",
|
||||
"required_field": "هذه الخانة مطلوبه",
|
||||
"displayname_min_length": "يجب أن يتكون اسم العرض من 3 أحرف على الأقل",
|
||||
"displayname_max_length": "يجب ألا يزيد طول اسم العرض عن 50 حرفًا",
|
||||
"report_profile": "الإبلاغ عن هذا الملف الشخصي",
|
||||
"report_reason": "لماذا تقوم بالإبلاغ عن هذا الملف الشخصي؟",
|
||||
"report_description": "معلومات إضافية",
|
||||
"report_description_placeholder": "معلومات إضافية",
|
||||
"report": "تقرير",
|
||||
"report_reason_hate": "خطاب الكراهية",
|
||||
"report_reason_sexual_content": "المحتوى الجنسي",
|
||||
"report_reason_violence": "عنف",
|
||||
"report_reason_spam": "رسائل إلكترونية مزعجة",
|
||||
"profile_reported": "تم الإبلاغ عن الملف الشخصي",
|
||||
"your_friend_code": "رمز صديقك:",
|
||||
"upload_banner": "تحميل لافتة",
|
||||
"uploading_banner": "جارٍ تحميل البانر…",
|
||||
"background_image_updated": "تم تحديث صورة الخلفية",
|
||||
"report_reason_zero": "آخر",
|
||||
"report_reason_one": "لماذا تقوم بالإبلاغ عن هذا الملف الشخصي؟",
|
||||
"report_reason_two": "آخر",
|
||||
"report_reason_few": "آخر",
|
||||
"report_reason_many": "آخر",
|
||||
"report_reason_other": "آخر"
|
||||
},
|
||||
"achievement": {
|
||||
"achievement_unlocked": "تم فتح الإنجاز",
|
||||
"user_achievements": "{{displayName}}إنجازات",
|
||||
"your_achievements": "إنجازاتك",
|
||||
"unlocked_at": "مقفلة في: {{date}}",
|
||||
"subscription_needed": "مطلوب اشتراك Hydra Cloud لرؤية هذا المحتوى",
|
||||
"new_achievements_unlocked": "مفتوح {{achievementCount}} انجازات جديدة من {{gameCount}} ألعاب",
|
||||
"achievement_progress": "{{unlockedCount}}/{{totalCount}} الإنجازات",
|
||||
"achievements_unlocked_for_game": "مفتوح {{achievementCount}} انجازات جديدة ل {{gameTitle}}"
|
||||
},
|
||||
"hydra_cloud": {
|
||||
"subscription_tour_title": "اشتراك Hydra كلاود",
|
||||
"subscribe_now": "اشترك الآن",
|
||||
"cloud_saving": "الحفظ السحابي",
|
||||
"cloud_achievements": "احفظ إنجازاتك على السحابة",
|
||||
"animated_profile_picture": "صور شخصية متحركة",
|
||||
"premium_support": "دعم متميز",
|
||||
"show_and_compare_achievements": "عرض ومقارنة إنجازاتك مع المستخدمين الآخرين",
|
||||
"animated_profile_banner": "لافتة الملف الشخصي المتحركة"
|
||||
}
|
||||
}
|
||||
|
||||
381
src/locales/bg/translation.json
Normal file
@@ -0,0 +1,381 @@
|
||||
{
|
||||
"language_name": "Български",
|
||||
"app": {
|
||||
"successfully_signed_in": "Успешно вписване"
|
||||
},
|
||||
"home": {
|
||||
"featured": "Препоръчани",
|
||||
"surprise_me": "Изненадай ме",
|
||||
"no_results": "Не са намерени резултати",
|
||||
"start_typing": "Търсене...",
|
||||
"hot": "Актуално сега",
|
||||
"weekly": "📅 Най-доброто от седмицата",
|
||||
"achievements": "🏆 Игри, които да победите"
|
||||
},
|
||||
"sidebar": {
|
||||
"catalogue": "Каталог",
|
||||
"downloads": "Изтегляния",
|
||||
"settings": "Настройки",
|
||||
"my_library": "Моята библиотека",
|
||||
"downloading_metadata": "{{title}} (Сваляне на метаданни…)",
|
||||
"paused": "{{title}} (Пауза)",
|
||||
"downloading": "{{title}} ({{percentage}} - Изтегляне…)",
|
||||
"filter": "Търсене по име",
|
||||
"home": "Начало",
|
||||
"queued": "{{title}} (Опашка)",
|
||||
"game_has_no_executable": "Играта няма избран изпълним файл",
|
||||
"sign_in": "Вписване",
|
||||
"friends": "Приятели",
|
||||
"need_help": "Имате нужда от помощ??"
|
||||
},
|
||||
"header": {
|
||||
"search": "Търсене",
|
||||
"home": "Начало",
|
||||
"catalogue": "Каталог",
|
||||
"downloads": "Изтегляния",
|
||||
"search_results": "Резултати от търсене",
|
||||
"settings": "Настройки",
|
||||
"version_available_install": "Версия {{version}} е налична. Кликни тук, за да рестартирате и инсталирате.",
|
||||
"version_available_download": "Версия {{version}} е налична. Кликни тук за изтегляне."
|
||||
},
|
||||
"bottom_panel": {
|
||||
"no_downloads_in_progress": "Няма изтегляния в ход",
|
||||
"downloading_metadata": "Сваляне на {{title}} метадата…",
|
||||
"downloading": "Изтегляне на {{title}}… ({{percentage}} готово) - Остават {{eta}} - {{speed}}",
|
||||
"calculating_eta": "Изтегляне на {{title}}… ({{percentage}} готово) - Изчисляване на оставащо време…",
|
||||
"checking_files": "Проверка на {{title}} файловете… ({{percentage}} готово)"
|
||||
},
|
||||
"catalogue": {
|
||||
"next_page": "Следваща страница",
|
||||
"previous_page": "Предишна страница"
|
||||
},
|
||||
"game_details": {
|
||||
"open_download_options": "Варианти за изтегляне",
|
||||
"download_options_zero": "Няма варианти за изтегляне",
|
||||
"download_options_one": "{{count}} варианти за изтегляне",
|
||||
"download_options_other": "{{count}} варианти за изтегляне",
|
||||
"updated_at": "Обновено на {{updated_at}}",
|
||||
"install": "Инсталирай",
|
||||
"resume": "Продължи",
|
||||
"pause": "Пауза",
|
||||
"cancel": "Отказ",
|
||||
"remove": "Премахни",
|
||||
"space_left_on_disk": "{{space}} място на диска",
|
||||
"eta": "Заклчение {{eta}}",
|
||||
"calculating_eta": "Калкулиране на оставащо време…",
|
||||
"downloading_metadata": "Изтегляне на метадата…",
|
||||
"filter": "Филтрирай repacks",
|
||||
"requirements": "Системни изисквания",
|
||||
"minimum": "Минимални",
|
||||
"recommended": "Препоръчителни",
|
||||
"paused": "Паузирано",
|
||||
"release_date": "Издадено на {{date}}",
|
||||
"publisher": "Публикувано от {{publisher}}",
|
||||
"hours": "часове",
|
||||
"minutes": "минути",
|
||||
"amount_hours": "{{amount}} часа",
|
||||
"amount_minutes": "{{amount}} минути",
|
||||
"accuracy": "{{accuracy}}% точност",
|
||||
"add_to_library": "Добави в библиотеката",
|
||||
"remove_from_library": "Премахни от библиотеката",
|
||||
"no_downloads": "Няма налични изтегляния",
|
||||
"play_time": "Игрално време {{amount}}",
|
||||
"last_time_played": "Последно пускане {{period}}",
|
||||
"not_played_yet": "Не сте играли {{title}} все още",
|
||||
"next_suggestion": "Следващо предложение",
|
||||
"play": "Пускане",
|
||||
"deleting": "Изтриване на инсталация…",
|
||||
"close": "Затвори",
|
||||
"playing_now": "Играй сега",
|
||||
"change": "Промяна",
|
||||
"repacks_modal_description": "Избери repack който искаш да изтеглиш",
|
||||
"select_folder_hint": "За да промените стандартната папка отидете в <0>Настройки</0>",
|
||||
"download_now": "Изтегли сега",
|
||||
"no_shop_details": "Не може да се извлекат данни за магазина.",
|
||||
"download_options": "Опции за сваляне",
|
||||
"download_path": "Път за сваляне",
|
||||
"previous_screenshot": "Предишна снимка",
|
||||
"next_screenshot": "Следваща снимка",
|
||||
"screenshot": "Снимка {{number}}",
|
||||
"open_screenshot": "Отвори снимки {{number}}",
|
||||
"download_settings": "Настройки за сваляне",
|
||||
"downloader": "Downloader",
|
||||
"select_executable": "Избери",
|
||||
"no_executable_selected": "Няма избран стартиращ файл",
|
||||
"open_folder": "Отвори папка",
|
||||
"open_download_location": "Виж свалените файлове",
|
||||
"create_shortcut": "Пряк път на Десктопа",
|
||||
"remove_files": "Премахни файловете",
|
||||
"remove_from_library_title": "Сигурен ли си?",
|
||||
"remove_from_library_description": "Това ще премахне {{game}} от Библиотеката",
|
||||
"options": "Опции",
|
||||
"executable_section_title": "Стартиращ файл",
|
||||
"executable_section_description": "Пътят на файла, който ще се изпълни, когато се щракне върху \"Пускане\"",
|
||||
"downloads_secion_title": "Свалени",
|
||||
"downloads_section_description": "Вижте актуализации или други версии на тази игра",
|
||||
"danger_zone_section_title": "Опасна зона",
|
||||
"danger_zone_section_description": "Премахнете тази игра от библиотеката си или от файловете, изтеглени от Hydra",
|
||||
"download_in_progress": "Изтегляне в ход",
|
||||
"download_paused": "Изтеглянето е паузирано",
|
||||
"last_downloaded_option": "Опция от последно изтегляне",
|
||||
"create_shortcut_success": "Прекият път е създаден успешно",
|
||||
"create_shortcut_error": "Грешка при създаването на пряк път",
|
||||
"nsfw_content_title": "Тази игра съдържа неподходящо съдържание",
|
||||
"nsfw_content_description": "{{title}} съдържа съдържание, което може да не е подходящо за всички възрасти. Сигурни ли сте, че искате да продължите?",
|
||||
"allow_nsfw_content": "Продължи",
|
||||
"refuse_nsfw_content": "Назад",
|
||||
"stats": "Статистики",
|
||||
"download_count": "Сваляния",
|
||||
"player_count": "Активни играчи",
|
||||
"download_error": "Тази опция за изтегляне не е налична",
|
||||
"download": "Свали",
|
||||
"executable_path_in_use": "Изпълнимият файл вече се използва от \"{{game}}\"",
|
||||
"warning": "Внимание:",
|
||||
"hydra_needs_to_remain_open": "за това изтегляне, Hydra трябва да остане отворена, когато е завършено. Ако Hydra се затвори преди завършването, ще загубите напредъка си..",
|
||||
"achievements": "Постижения",
|
||||
"achievements_count": "Постижения {{unlockedCount}}/{{achievementsCount}}",
|
||||
"cloud_save": "Запазване в облака",
|
||||
"cloud_save_description": "Запазете напредъка си в облака и продължете да играете на всяко устройство",
|
||||
"backups": "Резервни копия",
|
||||
"install_backup": "Инсталирай",
|
||||
"delete_backup": "Изтрий",
|
||||
"create_backup": "Ново копие",
|
||||
"last_backup_date": "Последно копие от {{date}}",
|
||||
"no_backup_preview": "Не бяха намерени запазени игри за това заглавие",
|
||||
"restoring_backup": "Възстановяване на резервно копие ({{progress}} готово)…",
|
||||
"uploading_backup": "Качване на резервно копие…",
|
||||
"no_backups": "Все още не сте създали резервни копия за тази игра",
|
||||
"backup_uploaded": "Качено резервно копие",
|
||||
"backup_deleted": "Изтрито резервно копие",
|
||||
"backup_restored": "Възстановен бекъп",
|
||||
"see_all_achievements": "Вижте всички постижения",
|
||||
"sign_in_to_see_achievements": "Влезте, за да видите постиженията",
|
||||
"mapping_method_automatic": "Автоматично",
|
||||
"mapping_method_manual": "Ръчно",
|
||||
"mapping_method_label": "Метод на картографиране",
|
||||
"files_automatically_mapped": "Автоматично картографиране на файлове",
|
||||
"no_backups_created": "Не са създадени резервни копия за тази игра",
|
||||
"manage_files": "Управление на файлове",
|
||||
"loading_save_preview": "Търсене на запазени игри…",
|
||||
"wine_prefix": "Wine Префикс",
|
||||
"wine_prefix_description": "Wine prefix използван за тази игра",
|
||||
"no_download_option_info": "Няма налични данни",
|
||||
"backup_deletion_failed": "Неуспешно изтриване на резервно копие",
|
||||
"max_number_of_artifacts_reached": "Достигнат максимален брой резервни копия за тази игра",
|
||||
"achievements_not_sync": "Постиженията не са синхронизирани",
|
||||
"manage_files_description": "Управлявайте кои файлове ще бъдат архивирани и възстановени",
|
||||
"select_folder": "Избери папка",
|
||||
"backup_from": "Резервно копие от {{date}}",
|
||||
"custom_backup_location_set": "Задаване на персонализирано местоположение за архивиране"
|
||||
},
|
||||
"activation": {
|
||||
"title": "Активирай Hydra",
|
||||
"installation_id": "Идентификатор на инсталацията:",
|
||||
"enter_activation_code": "Въведете кода за активиране",
|
||||
"message": "Ако не знаете къде да попитате за това, значи не трябва да го имате..",
|
||||
"activate": "Активирай",
|
||||
"loading": "Зареждане…"
|
||||
},
|
||||
"downloads": {
|
||||
"resume": "Продължи",
|
||||
"pause": "Пауза",
|
||||
"eta": "Conclusion {{eta}}",
|
||||
"paused": "Паузирано",
|
||||
"verifying": "Проверка…",
|
||||
"completed": "Готово",
|
||||
"removed": "Не е изтеглен",
|
||||
"cancel": "Отказ",
|
||||
"filter": "Филтриране на изтеглени игри",
|
||||
"remove": "Премахни",
|
||||
"downloading_metadata": "Изтегляне на метаданни…",
|
||||
"deleting": "Изтриване на инсталатора…",
|
||||
"delete": "Премахване на инсталатора",
|
||||
"delete_modal_title": "Сигурени ли сте?",
|
||||
"delete_modal_description": "Това ще премахне всички инсталационни файлове от компютъра ви.",
|
||||
"install": "Инсталирай",
|
||||
"download_in_progress": "В процес на изпълнение",
|
||||
"queued_downloads": "Изтеглени файлове в опашката",
|
||||
"downloads_completed": "Приключени",
|
||||
"queued": "В опашка",
|
||||
"no_downloads_title": "Толкова е празно",
|
||||
"no_downloads_description": "Все още не сте изтеглили нищо с Hydra, но никога не е късно да започнете...",
|
||||
"checking_files": "Проверка на файлове…"
|
||||
},
|
||||
"settings": {
|
||||
"downloads_path": "Инсталационен път",
|
||||
"change": "Актуализиране",
|
||||
"notifications": "Известия",
|
||||
"enable_download_notifications": "Когато изтеглянето е завършено",
|
||||
"enable_repack_list_notifications": "Когато се добави нов repack",
|
||||
"real_debrid_api_token_label": "Real-Debrid API токен",
|
||||
"quit_app_instead_hiding": "Не скривайте Hydra при затваряне",
|
||||
"launch_with_system": "Стартиране на Hydra при стартиране на системата",
|
||||
"general": "Общ",
|
||||
"behavior": "Поведение",
|
||||
"download_sources": "Източници за изтегляне",
|
||||
"language": "Език",
|
||||
"real_debrid_api_token": "API Токен",
|
||||
"enable_real_debrid": "Включи Real-Debrid",
|
||||
"real_debrid_description": "Real-Debrid е неограничен даунлоудър, който ви позволява бързо да изтегляте файлове, ограничени само от скоростта на интернет..",
|
||||
"real_debrid_invalid_token": "Невалиден API токен",
|
||||
"real_debrid_api_token_hint": "Вземете своя API токен <0>тук</0>",
|
||||
"real_debrid_free_account_error": "Акаунтът \"{{username}}\" е безплатен акаунт. Моля абонирай се за Real-Debrid",
|
||||
"real_debrid_linked_message": "Акаунтът \"{{username}}\" е свързан",
|
||||
"save_changes": "Запази промените",
|
||||
"changes_saved": "Промените са успешно запазни",
|
||||
"download_sources_description": "Hydra ще извлича връзките за изтегляне от тези източници. URL адресът на източника трябва да е директна връзка към .json файл, съдържащ връзките за изтегляне.",
|
||||
"validate_download_source": "Валидиране",
|
||||
"remove_download_source": "Премахни",
|
||||
"add_download_source": "Добави източник",
|
||||
"download_count_zero": "Няма опции за сваляне",
|
||||
"download_count_one": "{{countFormatted}} опции за сваляне",
|
||||
"download_count_other": "{{countFormatted}} опции за сваляне",
|
||||
"download_source_url": "URL адрес на източника за изтегляне",
|
||||
"add_download_source_description": "Вмъкнете URL адреса на файла .json",
|
||||
"download_source_up_to_date": "Актуален",
|
||||
"download_source_errored": "Сгрешен",
|
||||
"sync_download_sources": "Синхронизирай източниците",
|
||||
"removed_download_source": "Източника за сваляне е премахнат",
|
||||
"added_download_source": "Добавен източник за сваляне",
|
||||
"download_sources_synced": "Всички източници за сваляне са синхронизирани",
|
||||
"insert_valid_json_url": "Добавете ваиден JSON линк",
|
||||
"found_download_option_zero": "Няма намерени опции за сваляне",
|
||||
"found_download_option_one": "Намерени {{countFormatted}} опции за сваляне",
|
||||
"found_download_option_other": "Намерени {{countFormatted}} опции за сваляне",
|
||||
"import": "Внеси",
|
||||
"public": "Публичен",
|
||||
"private": "Личен",
|
||||
"friends_only": "Само за приятели",
|
||||
"privacy": "Поверителност",
|
||||
"profile_visibility": "Видимост на профила",
|
||||
"profile_visibility_description": "Изберете кой може да вижда вашия профил и библиотека",
|
||||
"required_field": "Това поле е задължително",
|
||||
"source_already_exists": "Този източник вече е добавен",
|
||||
"must_be_valid_url": "Източникът трябва да е валиден URL адрес.",
|
||||
"blocked_users": "Блокирани потребители",
|
||||
"user_unblocked": "Потребителят е бил деблокиран",
|
||||
"enable_achievement_notifications": "Когато е отключено постижение",
|
||||
"launch_minimized": "Стартиране на Hydra минимизирано",
|
||||
"disable_nsfw_alert": "Деактивиране на предупреждението NSFW"
|
||||
},
|
||||
"notifications": {
|
||||
"download_complete": "Изтеглянето е завършено",
|
||||
"game_ready_to_install": "{{title}} е готово за инсталиране",
|
||||
"repack_list_updated": "Repack лист е обновен",
|
||||
"repack_count_one": "{{count}} repack е добавен",
|
||||
"repack_count_other": "{{count}} repacks добавени",
|
||||
"new_update_available": "Версия {{version}} е налична",
|
||||
"restart_to_install_update": "Рестартирайте Hydra, за да инсталирате актуализацията",
|
||||
"notification_achievement_unlocked_title": "Отключено постижение за {{game}}",
|
||||
"notification_achievement_unlocked_body": "{{achievement}} и други {{count}} са отклщчени"
|
||||
},
|
||||
"system_tray": {
|
||||
"open": "Отвори Hydra",
|
||||
"quit": "Изход"
|
||||
},
|
||||
"game_card": {
|
||||
"no_downloads": "Няма налични изтегляния"
|
||||
},
|
||||
"binary_not_found_modal": {
|
||||
"title": "Не инсталирани програми",
|
||||
"description": "Wine или Lutris изпълними файлове не бяха открити на вашата система",
|
||||
"instructions": "Проверете правилния начин за инсталиране на някоя от тях на вашата дистрибуция на Linux, за да може играта да работи нормално"
|
||||
},
|
||||
"modal": {
|
||||
"close": "Бутон за затваряне"
|
||||
},
|
||||
"forms": {
|
||||
"toggle_password_visibility": "Превключване на видимостта на паролата"
|
||||
},
|
||||
"user_profile": {
|
||||
"amount_hours": "{{amount}} часове",
|
||||
"amount_minutes": "{{amount}} минути",
|
||||
"last_time_played": "Последно играно {{period}}",
|
||||
"activity": "Скорошна активност",
|
||||
"library": "Библиотека",
|
||||
"total_play_time": "Общо време за игра",
|
||||
"no_recent_activity_title": "Хмм… няма нищо тук",
|
||||
"no_recent_activity_description": "Не сте играли игри напоследък. Време е да промените това.!",
|
||||
"display_name": "Показване на името",
|
||||
"saving": "Запазване",
|
||||
"save": "Запис",
|
||||
"edit_profile": "Редактиране на профила",
|
||||
"saved_successfully": "Запазено успешно",
|
||||
"try_again": "Моля, опитайте пак",
|
||||
"sign_out_modal_title": "Сигурни ли сте?",
|
||||
"cancel": "Отказ",
|
||||
"successfully_signed_out": "Успешно се отписахте",
|
||||
"sign_out": "Отписване",
|
||||
"playing_for": "В игра от {{amount}}",
|
||||
"sign_out_modal_text": "Вашата библиотека е свързана с текущата ви сметка. Когато се отпишете, библиотеката ви вече няма да е видима и напредъкът няма да бъде запазен. Продължете с отписването?",
|
||||
"add_friends": "Добави приятели",
|
||||
"add": "Добави",
|
||||
"friend_code": "Приятелски код",
|
||||
"see_profile": "Виж профила",
|
||||
"sending": "Изпращане",
|
||||
"friend_request_sent": "Изпратена покана за приятелство",
|
||||
"friends": "Приятели",
|
||||
"friends_list": "Списък с приятели",
|
||||
"user_not_found": "Не е намерен потребител",
|
||||
"block_user": "Блокирай потребител",
|
||||
"add_friend": "Добави приятел",
|
||||
"request_sent": "Изпратена покана",
|
||||
"request_received": "Получена покана",
|
||||
"accept_request": "Приеми поканата",
|
||||
"ignore_request": "Игнирирай поканата",
|
||||
"cancel_request": "Откажи поканата",
|
||||
"undo_friendship": "Отмяна на приятелството",
|
||||
"request_accepted": "Поканата е приета",
|
||||
"user_blocked_successfully": "Потребителят е блокиран успешно",
|
||||
"user_block_modal_text": "Това ще блокира {{displayName}}",
|
||||
"blocked_users": "Блокирани потребители",
|
||||
"unblock": "Отблокирай",
|
||||
"no_friends_added": "Не сте добавили приятели",
|
||||
"pending": "Чакащи",
|
||||
"no_pending_invites": "Нямате чакащи покани",
|
||||
"no_blocked_users": "Нямате блокирани потребители",
|
||||
"friend_code_copied": "Приятелския код е копиран",
|
||||
"undo_friendship_modal_text": "Това ще отмени приятелството ви с {{displayName}}",
|
||||
"privacy_hint": "За да настроите кой може да вижда това, отидете в <0>Настройки</0>",
|
||||
"locked_profile": "Този профил е личен",
|
||||
"image_process_failure": "Грешка при обработката на изображението",
|
||||
"required_field": "Това поле е задължително",
|
||||
"displayname_min_length": "Името трябва да е дълго поне 3 символа",
|
||||
"displayname_max_length": "Името трябва да е с дължина не повече от 50 символа.",
|
||||
"report_profile": "Докладвай този профил",
|
||||
"report_reason": "Защо докладвате този профил?",
|
||||
"report_description": "Допълнителна информация",
|
||||
"report_description_placeholder": "Допълнителна информация",
|
||||
"report": "Докладвай",
|
||||
"report_reason_hate": "Омразна реч",
|
||||
"report_reason_sexual_content": "Сексуално съдържание",
|
||||
"report_reason_violence": "Насилия",
|
||||
"report_reason_spam": "Спам",
|
||||
"report_reason_other": "Друго",
|
||||
"profile_reported": "Профилът е докладван",
|
||||
"your_friend_code": "Вашия приятелски код:",
|
||||
"upload_banner": "Качи банер",
|
||||
"uploading_banner": "Качване на банер…",
|
||||
"background_image_updated": "Обновено фоново изображение"
|
||||
},
|
||||
"achievement": {
|
||||
"achievement_unlocked": "Постижението е отключено",
|
||||
"user_achievements": "Постиженията на {{displayName}} ",
|
||||
"your_achievements": "Вашите Постижения",
|
||||
"unlocked_at": "Отключено на: {{date}}",
|
||||
"subscription_needed": "Необходим е абонамент за Hydra Cloud, за да видите това съдържание",
|
||||
"new_achievements_unlocked": "Отключени {{achievementCount}} нови постижения от {{gameCount}} игра",
|
||||
"achievement_progress": "{{unlockedCount}}/{{totalCount}} постижения",
|
||||
"achievements_unlocked_for_game": "Отключени {{achievementCount}} нови постижения за {{gameTitle}}"
|
||||
},
|
||||
"hydra_cloud": {
|
||||
"subscription_tour_title": "Hydra Cloud Абонамент",
|
||||
"subscribe_now": "Абонирай се сега",
|
||||
"cloud_saving": "Запазване в облака",
|
||||
"cloud_achievements": "Запазете постиженията си в облака",
|
||||
"animated_profile_picture": "Анимирана профилна снимка",
|
||||
"premium_support": "Премиум поддръжка",
|
||||
"show_and_compare_achievements": "Показвайте и сравнявайте постиженията си с тези на други потребители",
|
||||
"animated_profile_banner": "Анимиран профилен банер"
|
||||
}
|
||||
}
|
||||
@@ -224,7 +224,7 @@
|
||||
"last_time_played": "Última partida {{period}}",
|
||||
"activity": "Activitat recent",
|
||||
"library": "Biblioteca",
|
||||
"total_play_time": "Temps total de joc:{{amount}}",
|
||||
"total_play_time": "Temps total de joc",
|
||||
"no_recent_activity_title": "Hmmm… encara no res",
|
||||
"no_recent_activity_description": "No has jugat a cap joc recentment. És el moment de canviar-ho!",
|
||||
"display_name": "Nom de visualització",
|
||||
|
||||
@@ -6,7 +6,11 @@
|
||||
"home": {
|
||||
"featured": "Doporučené",
|
||||
"surprise_me": "Překvap mě",
|
||||
"no_results": "Výsledek nenalezen"
|
||||
"no_results": "Výsledek nenalezen",
|
||||
"start_typing": "Začni psát pro vyhledávání...",
|
||||
"hot": "Teď populární",
|
||||
"weekly": "📅 Nejlepší hry týdne",
|
||||
"achievements": "🏆 Hry k překonání"
|
||||
},
|
||||
"sidebar": {
|
||||
"catalogue": "Katalog",
|
||||
@@ -20,7 +24,9 @@
|
||||
"home": "Domov",
|
||||
"queued": "{{title}} (V řadě)",
|
||||
"game_has_no_executable": "Hra nemá zvolen žádný spustitelný soubor",
|
||||
"sign_in": "Přihlásit se"
|
||||
"sign_in": "Přihlásit se",
|
||||
"friends": "Přátelé",
|
||||
"need_help": "Potřebujete pomoc?"
|
||||
},
|
||||
"header": {
|
||||
"search": "Vyhledat hry",
|
||||
@@ -113,7 +119,54 @@
|
||||
"download_paused": "Stahování pozastaveno",
|
||||
"last_downloaded_option": "Poslední stažená možnost",
|
||||
"create_shortcut_success": "Zástupce vytvořen úspěšně",
|
||||
"create_shortcut_error": "Chyba při pokusu vytvořit zástupce"
|
||||
"create_shortcut_error": "Chyba při pokusu vytvořit zástupce",
|
||||
"nsfw_content_title": "Tahle hra obsahuje nevhodný obsah",
|
||||
"nsfw_content_description": "{{title}} obsahuje obsah, který by nemusel být vhodný pro všechny věkové skupiny. Jste si jisti, že chcete pokračovat?",
|
||||
"allow_nsfw_content": "Pokračovat",
|
||||
"refuse_nsfw_content": "Jít zpět",
|
||||
"stats": "Statistiky",
|
||||
"download_count": "Stažení",
|
||||
"player_count": "Aktivní hráči",
|
||||
"download_error": "Tahle možnost stažení není dostupná",
|
||||
"download": "Stáhnout",
|
||||
"executable_path_in_use": "Spustitelný soubor již používá \"{{game}}\"",
|
||||
"warning": "Varování",
|
||||
"hydra_needs_to_remain_open": "Pro tohle stažení, musí Hydra zůstat otevřená až do konce stahování. Pokud Hydru zavřete dříve, postup stahování bude ztracen.",
|
||||
"achievements": "Achievementy",
|
||||
"achievements_count": "Achievementy {{unlockedCount}}/{{achievementsCount}}",
|
||||
"cloud_save": "Uložení v cloudu",
|
||||
"cloud_save_description": "Uložte si svůj postup v cloud a pokračujte v hraní na jakémkoliv zářízení",
|
||||
"backups": "Zálohy",
|
||||
"install_backup": "Nainstalovat",
|
||||
"delete_backup": "Smazat",
|
||||
"create_backup": "Vytvořit zálohu",
|
||||
"last_backup_date": "Poslední záloha vytvořena {{date}}",
|
||||
"no_backup_preview": "Žádné zálohy nebyly nalezeny pro tuhle hru",
|
||||
"restoring_backup": "Obnovuji zálohu ({{progress}} hotovo)...",
|
||||
"uploading_backup": "Nahrávání zálohy...",
|
||||
"no_backups": "Nemáte zatím vytvořeny žádné zálohy pro tuto hru",
|
||||
"backup_uploaded": "Záloha nahrána",
|
||||
"backup_deleted": "Záloha odstraněna",
|
||||
"backup_restored": "Záloha obnovena",
|
||||
"see_all_achievements": "Zobrazit všechny achievementy",
|
||||
"sign_in_to_see_achievements": "Musíte se přihlásit pro zobrazení achievementů",
|
||||
"mapping_method_automatic": "Automaticky",
|
||||
"mapping_method_manual": "Manuálně",
|
||||
"mapping_method_label": "Metoda mapování",
|
||||
"files_automatically_mapped": "Soubory automaticky zmapovány",
|
||||
"no_backups_created": "Žádné zálohy nebyly vytvořeny pro tuto hru",
|
||||
"manage_files": "Spravovat soubory",
|
||||
"loading_save_preview": "Hledání uložených her...",
|
||||
"wine_prefix": "Wine Prefix",
|
||||
"wine_prefix_description": "Wine Prefix použit pro spuštění této hry",
|
||||
"no_download_option_info": "Žádné informace nejsou dostupny",
|
||||
"backup_deletion_failed": "Nepovedlo se odstranit zálohu",
|
||||
"max_number_of_artifacts_reached": "Dosáhli jste maximálního počtu záloh pro tuto hru",
|
||||
"achievements_not_sync": "Vaše achievementy nejsou synchronizovány",
|
||||
"manage_files_description": "Spravovat, které soubory budou zálohovány a obnoveny",
|
||||
"select_folder": "Vybrat složku",
|
||||
"backup_from": "Zálohy z {{date}}",
|
||||
"custom_backup_location_set": "Vlastní umístění záloh nastaveno"
|
||||
},
|
||||
"activation": {
|
||||
"title": "Aktivovat hydru",
|
||||
@@ -189,7 +242,21 @@
|
||||
"found_download_option_zero": "Nenalezena žádná možnost stahování",
|
||||
"found_download_option_one": "Nalezena {{countFormatted}} možnost stahování",
|
||||
"found_download_option_other": "Nalezeny {{countFormatted}} možnosti stahování",
|
||||
"import": "Importovat"
|
||||
"import": "Importovat",
|
||||
"public": "Veřejné",
|
||||
"private": "Soukromé",
|
||||
"friends_only": "Pouze přátelé",
|
||||
"privacy": "Soukromí",
|
||||
"profile_visibility": "Viditelnost profilu",
|
||||
"profile_visibility_description": "Vyberte si, kdo může vidět váš profil a knihovnu",
|
||||
"required_field": "Toto pole je povinné",
|
||||
"source_already_exists": "Tento zdroj byl již přidán",
|
||||
"must_be_valid_url": "Zdroj musí být platký odkaz URL",
|
||||
"blocked_users": "Zablokovaní uživatelé",
|
||||
"user_unblocked": "Uživatel byl odblokován",
|
||||
"enable_achievement_notifications": "Když je odemknut achievement",
|
||||
"launch_minimized": "Spustit v minimalizovaném režimu",
|
||||
"disable_nsfw_alert": "Deaktivovat upozornění na nevhodný obsah"
|
||||
},
|
||||
"notifications": {
|
||||
"download_complete": "Stahování dokončeno",
|
||||
@@ -198,7 +265,9 @@
|
||||
"repack_count_one": "{{count}} repack přidán",
|
||||
"repack_count_other": "{{count}} repacky přidány",
|
||||
"new_update_available": "Version {{version}} je dostupná",
|
||||
"restart_to_install_update": "Restartuj Hydru pro aktualizaci"
|
||||
"restart_to_install_update": "Restartuj Hydru pro aktualizaci",
|
||||
"notification_achievement_unlocked_title": "Achievement pro {{game}} byl odemknut",
|
||||
"notification_achievement_unlocked_body": "{{achievement}} a dalších {{count}} byly odemknuty"
|
||||
},
|
||||
"system_tray": {
|
||||
"open": "Otevřít Hydru",
|
||||
@@ -224,7 +293,7 @@
|
||||
"last_time_played": "Naposledy hráno {{period}}",
|
||||
"activity": "Nedávná aktivita",
|
||||
"library": "Knihovna",
|
||||
"total_play_time": "Celkový odehraný čas: {{amount}}",
|
||||
"total_play_time": "Celkový odehraný čas",
|
||||
"no_recent_activity_title": "Hmmm… nic tu není",
|
||||
"no_recent_activity_description": "V poslední době si nehrál žádnout hru, můžeš to ale napravit!",
|
||||
"display_name": "Zobrazované jméno",
|
||||
@@ -266,6 +335,47 @@
|
||||
"no_pending_invites": "Nemáte žádné příchozí žádosti",
|
||||
"no_blocked_users": "Nemáte nikoho zablokovaného",
|
||||
"friend_code_copied": "Kód přítele zkopírován",
|
||||
"undo_friendship_modal_text": "Tímto zrušíte své přátelství s {{displayName}}"
|
||||
"undo_friendship_modal_text": "Tímto zrušíte své přátelství s {{displayName}}",
|
||||
"privacy_hint": "Pro změnu toho, kdo tohle může vidět, jděte do <0>Nastavení</0>",
|
||||
"locked_profile": "Tento profil je soukromý",
|
||||
"image_process_failure": "Nastala chyba při zpracování obrázku",
|
||||
"required_field": "Toto pole je povinné",
|
||||
"displayname_min_length": "Uživatelské jméno musí být minimálně 3 znaky dlouhé",
|
||||
"displayname_max_length": "Uživatelské jméno musí být maximálně 50 znaků dlouhé",
|
||||
"report_profile": "Nahlásit profil",
|
||||
"report_reason": "Proč nahlašujete tento profil?",
|
||||
"report_description": "Přídavné informace",
|
||||
"report_description_placeholder": "Přídavné informace",
|
||||
"report": "Nahlásit",
|
||||
"report_reason_hate": "Nenávistné projevy",
|
||||
"report_reason_sexual_content": "Sexuální obsah",
|
||||
"report_reason_violence": "Násilí",
|
||||
"report_reason_spam": "Spam",
|
||||
"report_reason_other": "Ostatní",
|
||||
"profile_reported": "Profil nahlášen",
|
||||
"your_friend_code": "Tvůj kód přítele:",
|
||||
"upload_banner": "Nahrát banner profilu",
|
||||
"uploading_banner": "Nahrávání banneru",
|
||||
"background_image_updated": "Obrázek pozadí byl změněn"
|
||||
},
|
||||
"achievement": {
|
||||
"achievement_unlocked": "Achievement odemčen",
|
||||
"user_achievements": "Achievementy uživatele {{displayName}}",
|
||||
"your_achievements": "Vaše achievementy",
|
||||
"unlocked_at": "Odemčeno: {{date}}",
|
||||
"subscription_needed": "Je vyžadováno předplatné Hydra Cloud pro zobrazení tohoto obsahu",
|
||||
"new_achievements_unlocked": "Odemčeno {{achievementCount}} nových achievementů z {{gameCount}} her",
|
||||
"achievement_progress": "{{unlockedCount}}/{{totalCount}} achievementů",
|
||||
"achievements_unlocked_for_game": "Odemčeno {{achievementCount}} nových achievementů pro {{gameTitle}}"
|
||||
},
|
||||
"hydra_cloud": {
|
||||
"subscription_tour_title": "Předplatné Hydra Cloud",
|
||||
"subscribe_now": "Připojit se",
|
||||
"cloud_saving": "Ukládání v cloudu",
|
||||
"cloud_achievements": "Ukládejte vaše achievementy do cloudu",
|
||||
"animated_profile_picture": "Animované profilové obrázky",
|
||||
"premium_support": "Prémiová podpora",
|
||||
"show_and_compare_achievements": "Zobraz a porovnej achievementy s ostatními uživateli",
|
||||
"animated_profile_banner": "Animovaný banner na profilu"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,7 +251,7 @@
|
||||
"last_time_played": "Sidst spillet {{period}}",
|
||||
"activity": "Seneste aktivitet",
|
||||
"library": "Bibliotek",
|
||||
"total_play_time": "Samlet spiltid: {{amount}}",
|
||||
"total_play_time": "Samlet spiltid",
|
||||
"no_recent_activity_title": "Hmmm… ikke noget her",
|
||||
"no_recent_activity_description": "Du har ikke spillet nogen spil for nyligt. Dét er det på tide at lave om på!",
|
||||
"display_name": "Brugernavn",
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
"last_time_played": "Zuletzt gespielt {{period}}",
|
||||
"activity": "Letzte Aktivität",
|
||||
"library": "Bibliothek",
|
||||
"total_play_time": "Gesamtspielzeit: {{amount}}",
|
||||
"total_play_time": "Gesamtspielzeit",
|
||||
"no_recent_activity_title": "Hmmm… hier ist nichts",
|
||||
"no_recent_activity_description": "Du hast in letzter Zeit keine Spiele gespielt. Es wird Zeit das zu ändern!",
|
||||
"display_name": "Anzeigename",
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
"queued": "{{title}} (Queued)",
|
||||
"game_has_no_executable": "Game has no executable selected",
|
||||
"sign_in": "Sign in",
|
||||
"friends": "Friends"
|
||||
"friends": "Friends",
|
||||
"need_help": "Need help?"
|
||||
},
|
||||
"header": {
|
||||
"search": "Search games",
|
||||
@@ -45,8 +46,15 @@
|
||||
"checking_files": "Checking {{title}} files… ({{percentage}} complete)"
|
||||
},
|
||||
"catalogue": {
|
||||
"next_page": "Next page",
|
||||
"previous_page": "Previous page"
|
||||
"search": "Filter…",
|
||||
"developers": "Developers",
|
||||
"genres": "Genres",
|
||||
"tags": "Tags",
|
||||
"publishers": "Publishers",
|
||||
"download_sources": "Download sources",
|
||||
"result_count": "{{resultCount}} results",
|
||||
"filter_count": "{{filterCount}} available",
|
||||
"clear_filters": "Clear {{filterCount}} selected"
|
||||
},
|
||||
"game_details": {
|
||||
"open_download_options": "Open download options",
|
||||
@@ -104,6 +112,7 @@
|
||||
"open_folder": "Open folder",
|
||||
"open_download_location": "See downloaded files",
|
||||
"create_shortcut": "Create desktop shortcut",
|
||||
"clear": "Clear",
|
||||
"remove_files": "Remove files",
|
||||
"remove_from_library_title": "Are you sure?",
|
||||
"remove_from_library_description": "This will remove {{game}} from your library",
|
||||
@@ -130,7 +139,7 @@
|
||||
"download": "Download",
|
||||
"executable_path_in_use": "Executable already in use by \"{{game}}\"",
|
||||
"warning": "Warning:",
|
||||
"hydra_needs_to_remain_open": "for this download, Hydra needs to remain open util its conclusion. In case Hydra closes before the conclusion, you will lose your progress.",
|
||||
"hydra_needs_to_remain_open": "for this download, Hydra needs to remain open util it's completed. If Hydra closes before completing, you will lose your progress.",
|
||||
"achievements": "Achievements",
|
||||
"achievements_count": "Achievements {{unlockedCount}}/{{achievementsCount}}",
|
||||
"cloud_save": "Cloud save",
|
||||
@@ -161,11 +170,12 @@
|
||||
"no_download_option_info": "No information available",
|
||||
"backup_deletion_failed": "Failed to delete backup",
|
||||
"max_number_of_artifacts_reached": "Maximum number of backups reached for this game",
|
||||
"achievements_not_sync": "Your achievements are not synchronized",
|
||||
"achievements_not_sync": "See how to synchronize your achievements",
|
||||
"manage_files_description": "Manage which files will be backed up and restored",
|
||||
"select_folder": "Select folder",
|
||||
"backup_from": "Backup from {{date}}",
|
||||
"custom_backup_location_set": "Custom backup location set"
|
||||
"custom_backup_location_set": "Custom backup location set",
|
||||
"no_directory_selected": "No directory selected"
|
||||
},
|
||||
"activation": {
|
||||
"title": "Activate Hydra",
|
||||
@@ -198,7 +208,11 @@
|
||||
"queued": "Queued",
|
||||
"no_downloads_title": "Such empty",
|
||||
"no_downloads_description": "You haven't downloaded anything with Hydra yet, but it's never too late to start.",
|
||||
"checking_files": "Checking files…"
|
||||
"checking_files": "Checking files…",
|
||||
"seeding": "Seeding",
|
||||
"stop_seeding": "Stop seeding",
|
||||
"resume_seeding": "Resume seeding",
|
||||
"options": "Manage"
|
||||
},
|
||||
"settings": {
|
||||
"downloads_path": "Downloads path",
|
||||
@@ -215,7 +229,7 @@
|
||||
"language": "Language",
|
||||
"real_debrid_api_token": "API Token",
|
||||
"enable_real_debrid": "Enable Real-Debrid",
|
||||
"real_debrid_description": "Real-Debrid is an unrestricted downloader that allows you to download files instantly and at the best of your Internet speed.",
|
||||
"real_debrid_description": "Real-Debrid is an unrestricted downloader that allows you to quickly download files, only limited by your internet speed.",
|
||||
"real_debrid_invalid_token": "Invalid API token",
|
||||
"real_debrid_api_token_hint": "You can get your API token <0>here</0>",
|
||||
"real_debrid_free_account_error": "The account \"{{username}}\" is a free account. Please subscribe to Real-Debrid",
|
||||
@@ -230,7 +244,7 @@
|
||||
"download_count_one": "{{countFormatted}} download option",
|
||||
"download_count_other": "{{countFormatted}} download options",
|
||||
"download_source_url": "Download source URL",
|
||||
"add_download_source_description": "Insert the URL containing the .json file",
|
||||
"add_download_source_description": "Insert the URL of the .json file",
|
||||
"download_source_up_to_date": "Up-to-date",
|
||||
"download_source_errored": "Errored",
|
||||
"sync_download_sources": "Sync sources",
|
||||
@@ -249,12 +263,15 @@
|
||||
"profile_visibility": "Profile visibility",
|
||||
"profile_visibility_description": "Choose who can see your profile and library",
|
||||
"required_field": "This field is required",
|
||||
"source_already_exists": "This source has been already added",
|
||||
"source_already_exists": "This source has already been added",
|
||||
"must_be_valid_url": "The source must be a valid URL",
|
||||
"blocked_users": "Blocked users",
|
||||
"user_unblocked": "User has been unblocked",
|
||||
"enable_achievement_notifications": "When an achievement in unlocked",
|
||||
"launch_minimized": "Launch Hydra minimized"
|
||||
"enable_achievement_notifications": "When an achievement is unlocked",
|
||||
"launch_minimized": "Launch Hydra minimized",
|
||||
"disable_nsfw_alert": "Disable NSFW alert",
|
||||
"seed_after_download_complete": "Seed after download complete",
|
||||
"show_hidden_achievement_description": "Show hidden achievements description before unlocking them"
|
||||
},
|
||||
"notifications": {
|
||||
"download_complete": "Download complete",
|
||||
@@ -289,9 +306,9 @@
|
||||
"amount_hours": "{{amount}} hours",
|
||||
"amount_minutes": "{{amount}} minutes",
|
||||
"last_time_played": "Last played {{period}}",
|
||||
"activity": "Recent activity",
|
||||
"activity": "Recent Activity",
|
||||
"library": "Library",
|
||||
"total_play_time": "Total playtime: {{amount}}",
|
||||
"total_play_time": "Total playtime",
|
||||
"no_recent_activity_title": "Hmmm… nothing here",
|
||||
"no_recent_activity_description": "You haven't played any games recently. It's time to change that!",
|
||||
"display_name": "Display name",
|
||||
@@ -328,7 +345,7 @@
|
||||
"user_block_modal_text": "This will block {{displayName}}",
|
||||
"blocked_users": "Blocked users",
|
||||
"unblock": "Unblock",
|
||||
"no_friends_added": "You still don't have added friends",
|
||||
"no_friends_added": "You have no added friends",
|
||||
"pending": "Pending",
|
||||
"no_pending_invites": "You have no pending invites",
|
||||
"no_blocked_users": "You have no blocked users",
|
||||
@@ -354,17 +371,34 @@
|
||||
"your_friend_code": "Your friend code:",
|
||||
"upload_banner": "Upload banner",
|
||||
"uploading_banner": "Uploading banner…",
|
||||
"background_image_updated": "Background image updated"
|
||||
"background_image_updated": "Background image updated",
|
||||
"stats": "Stats",
|
||||
"achievements": "achievements",
|
||||
"games": "Games",
|
||||
"top_percentile": "Top {{percentile}}%",
|
||||
"ranking_updated_weekly": "Ranking is updated weekly",
|
||||
"playing": "Playing {{game}}",
|
||||
"achievements_unlocked": "Achievements Unlocked",
|
||||
"earned_points": "Earned points",
|
||||
"show_achievements_on_profile": "Show your achievements on your profile",
|
||||
"show_points_on_profile": "Show your earned points on your profile"
|
||||
},
|
||||
"achievement": {
|
||||
"achievement_unlocked": "Achievement unlocked",
|
||||
"user_achievements": "{{displayName}}'s Achievements",
|
||||
"your_achievements": "Your Achievements",
|
||||
"unlocked_at": "Unlocked at:",
|
||||
"unlocked_at": "Unlocked at: {{date}}",
|
||||
"subscription_needed": "A Hydra Cloud subscription is required to see this content",
|
||||
"new_achievements_unlocked": "Unlocked {{achievementCount}} new achievements from {{gameCount}} games"
|
||||
"new_achievements_unlocked": "Unlocked {{achievementCount}} new achievements from {{gameCount}} games",
|
||||
"achievement_progress": "{{unlockedCount}}/{{totalCount}} achievements",
|
||||
"achievements_unlocked_for_game": "Unlocked {{achievementCount}} new achievements for {{gameTitle}}",
|
||||
"hidden_achievement_tooltip": "This is a hidden achievement",
|
||||
"achievement_earn_points": "Earn {{points}} points with this achievement",
|
||||
"earned_points": "Earned points:",
|
||||
"available_points": "Available points:",
|
||||
"how_to_earn_achievements_points": "How to earn achievements points?"
|
||||
},
|
||||
"tour": {
|
||||
"hydra_cloud": {
|
||||
"subscription_tour_title": "Hydra Cloud Subscription",
|
||||
"subscribe_now": "Subscribe now",
|
||||
"cloud_saving": "Cloud saving",
|
||||
@@ -372,6 +406,9 @@
|
||||
"animated_profile_picture": "Animated profile pictures",
|
||||
"premium_support": "Premium Support",
|
||||
"show_and_compare_achievements": "Show and compare your achievements to other users",
|
||||
"animated_profile_banner": "Animated profile banner"
|
||||
"animated_profile_banner": "Animated profile banner",
|
||||
"hydra_cloud": "Hydra Cloud",
|
||||
"hydra_cloud_feature_found": "You've just discovered a Hydra Cloud feature!",
|
||||
"learn_more": "Learn More"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
"queued": "{{title}} (En cola)",
|
||||
"game_has_no_executable": "El juego no tiene un ejecutable seleccionado",
|
||||
"sign_in": "Iniciar sesión",
|
||||
"friends": "Amigos"
|
||||
"friends": "Amigos",
|
||||
"need_help": "¿Necesitas ayuda?"
|
||||
},
|
||||
"header": {
|
||||
"search": "Buscar juegos",
|
||||
@@ -45,8 +46,15 @@
|
||||
"checking_files": "Verificando archivos de {{title}}… ({{percentage}} completado)"
|
||||
},
|
||||
"catalogue": {
|
||||
"next_page": "Siguiente página",
|
||||
"previous_page": "Pagina anterior"
|
||||
"search": "Filtrar…",
|
||||
"developers": "Desarrolladores",
|
||||
"genres": "Géneros",
|
||||
"tags": "Marcadores",
|
||||
"publishers": "Distribuidoras",
|
||||
"download_sources": "Fuentes de descarga",
|
||||
"result_count": "{{resultCount}} resultados",
|
||||
"filter_count": "{{filterCount}} disponibles",
|
||||
"clear_filters": "Limpiar {{filterCount}} seleccionados"
|
||||
},
|
||||
"game_details": {
|
||||
"open_download_options": "Ver opciones de descargas",
|
||||
@@ -78,7 +86,7 @@
|
||||
"add_to_library": "Agregar a la biblioteca",
|
||||
"remove_from_library": "Eliminar de la biblioteca",
|
||||
"no_downloads": "No hay descargas disponibles",
|
||||
"play_time": "Jugado por {{amount}}",
|
||||
"play_time": "Has jugado {{amount}}",
|
||||
"last_time_played": "Jugado por última vez: {{period}}",
|
||||
"not_played_yet": "Aún no has jugado a {{title}}",
|
||||
"next_suggestion": "Siguiente sugerencia",
|
||||
@@ -99,7 +107,7 @@
|
||||
"open_screenshot": "Abrir captura {{number}}",
|
||||
"download_settings": "Ajustes de descarga",
|
||||
"downloader": "Método de descarga",
|
||||
"select_executable": "Seleccionar ejecutable",
|
||||
"select_executable": "Seleccionar",
|
||||
"no_executable_selected": "No se seleccionó un ejecutable",
|
||||
"open_folder": "Abrir carpeta",
|
||||
"open_download_location": "Ver archivos descargados",
|
||||
@@ -165,7 +173,9 @@
|
||||
"manage_files_description": "Gestiona los archivos que serán respaldados y restaurados",
|
||||
"select_folder": "Seleccionar carpeta",
|
||||
"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",
|
||||
"no_directory_selected": "No se seleccionó un directório"
|
||||
},
|
||||
"activation": {
|
||||
"title": "Activar Hydra",
|
||||
@@ -253,7 +263,9 @@
|
||||
"must_be_valid_url": "La fuente debe ser una URL válida.",
|
||||
"blocked_users": "Usuarios bloqueados",
|
||||
"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",
|
||||
"disable_nsfw_alert": "Desactivar alerta NSFW"
|
||||
},
|
||||
"notifications": {
|
||||
"download_complete": "Descarga completada",
|
||||
@@ -290,7 +302,7 @@
|
||||
"last_time_played": "Última vez jugado: {{period}}",
|
||||
"activity": "Actividad reciente",
|
||||
"library": "Biblioteca",
|
||||
"total_play_time": "Total de tiempo jugado: {{amount}}",
|
||||
"total_play_time": "Has jugado",
|
||||
"no_recent_activity_title": "Que raro, no hay nada por acá...",
|
||||
"no_recent_activity_description": "No has jugado ningún juego recientemente, ¡vamos a cambiar eso ahora!",
|
||||
"display_name": "Nombre en pantalla",
|
||||
@@ -303,7 +315,7 @@
|
||||
"cancel": "Cancelar",
|
||||
"successfully_signed_out": "Sesión cerrada exitosamente",
|
||||
"sign_out": "Cerrar sesión",
|
||||
"playing_for": "Jugando por {{amount}}",
|
||||
"playing_for": "Llevas jugando {{amount}}",
|
||||
"sign_out_modal_text": "Tu biblioteca se ha vinculado con tu cuenta. Cuando cierres sesión, tú biblioteca ya no será visible y cualquier progreso no se guardará. ¿Continuar con el cierre de sesión?",
|
||||
"add_friends": "Añadir amigos",
|
||||
"add": "Añadir",
|
||||
@@ -353,17 +365,20 @@
|
||||
"your_friend_code": "Tu código de amigo:",
|
||||
"upload_banner": "Subir un banner",
|
||||
"uploading_banner": "Subiendo banner…",
|
||||
"background_image_updated": "Imagen de fondo actualizada"
|
||||
"background_image_updated": "Imagen de fondo actualizada",
|
||||
"playing": "Jugando {{game}}"
|
||||
},
|
||||
"achievement": {
|
||||
"achievement_unlocked": "Logro desbloqueado",
|
||||
"user_achievements": "Logros de {{displayName}}",
|
||||
"your_achievements": "Tus Logros",
|
||||
"unlocked_at": "Desbloqueado el:",
|
||||
"subscription_needed": "Se necesita una suscripción a Hydra Cloud se necesita para ver este contenido",
|
||||
"new_achievements_unlocked": "Desbloqueados {{achievementCount}} nuevos logros de {{gameCount}} juegos"
|
||||
"unlocked_at": "Desbloqueado el: {{date}}",
|
||||
"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",
|
||||
"achievement_progress": "{{unlockedCount}}/{{totalCount}} logros",
|
||||
"achievements_unlocked_for_game": "Se han desbloqueado {{achievementCount}} nuevos logros de {{gameTitle}}"
|
||||
},
|
||||
"tour": {
|
||||
"hydra_cloud": {
|
||||
"subscription_tour_title": "Suscripción Hydra Cloud",
|
||||
"subscribe_now": "Suscribirse ahora",
|
||||
"cloud_saving": "Guardado en la nube",
|
||||
|
||||
@@ -290,7 +290,7 @@
|
||||
"last_time_played": "Viimati mängitud {{period}}",
|
||||
"activity": "Hiljutine aktiivsus",
|
||||
"library": "Kogu",
|
||||
"total_play_time": "Kogu mängitud aeg: {{amount}}",
|
||||
"total_play_time": "Kogu mängitud aeg",
|
||||
"no_recent_activity_title": "Hmmm… siin pole midagi",
|
||||
"no_recent_activity_description": "Sa pole hiljuti ühtegi mängu mänginud. On aeg seda muuta!",
|
||||
"display_name": "Kuvatav nimi",
|
||||
@@ -359,11 +359,11 @@
|
||||
"achievement_unlocked": "Saavutus avatud",
|
||||
"user_achievements": "{{displayName}} saavutused",
|
||||
"your_achievements": "Sinu saavutused",
|
||||
"unlocked_at": "Avatud:",
|
||||
"unlocked_at": "Avatud: {{date}}",
|
||||
"subscription_needed": "Selle sisu nägemiseks on vaja Hydra Cloud tellimust",
|
||||
"new_achievements_unlocked": "Avatud {{achievementCount}} uut saavutust {{gameCount}} mängust"
|
||||
},
|
||||
"tour": {
|
||||
"hydra_cloud": {
|
||||
"subscription_tour_title": "Hydra Cloud Tellimus",
|
||||
"subscribe_now": "Telli kohe",
|
||||
"cloud_saving": "Pilvesalvestus",
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
"last_time_played": "Terakhir dimainkan {{period}}",
|
||||
"activity": "Aktivitas terbaru",
|
||||
"library": "Perpustakaan",
|
||||
"total_play_time": "Total waktu bermain: {{amount}}",
|
||||
"total_play_time": "Total waktu bermain",
|
||||
"no_recent_activity_title": "Hmm… kosong di sini",
|
||||
"no_recent_activity_description": "Kamu belum main game baru-baru ini. Yuk, mulai main!",
|
||||
"display_name": "Nama tampilan",
|
||||
|
||||
@@ -24,6 +24,7 @@ import kk from "./kk/translation.json";
|
||||
import cs from "./cs/translation.json";
|
||||
import nb from "./nb/translation.json";
|
||||
import et from "./et/translation.json";
|
||||
import bg from "./bg/translation.json";
|
||||
|
||||
export default {
|
||||
"pt-BR": ptBR,
|
||||
@@ -48,6 +49,7 @@ export default {
|
||||
fa,
|
||||
ro,
|
||||
ca,
|
||||
bg,
|
||||
kk,
|
||||
cs,
|
||||
nb,
|
||||
|
||||
@@ -220,7 +220,7 @@
|
||||
"last_time_played": "Соңғы ойын {{period}}",
|
||||
"activity": "Соңғы әрекет",
|
||||
"library": "Кітапхана",
|
||||
"total_play_time": "Барлығы ойнаған: {{amount}}",
|
||||
"total_play_time": "Барлығы ойнаған",
|
||||
"no_recent_activity_title": "Хммм... Мұнда ештеңе жоқ",
|
||||
"no_recent_activity_description": "Сіз ұзақ уақыт бойы ештеңе ойнаған жоқсыз. Мұны өзгерту керек!",
|
||||
"display_name": "Көрсету аты",
|
||||
|
||||
@@ -251,7 +251,7 @@
|
||||
"last_time_played": "Sist spilt {{period}}",
|
||||
"activity": "Seneste aktivitet",
|
||||
"library": "Bibliotek",
|
||||
"total_play_time": "Samlet spilltid: {{amount}}",
|
||||
"total_play_time": "Samlet spilltid",
|
||||
"no_recent_activity_title": "Hmmm… ikke noe her",
|
||||
"no_recent_activity_description": "Du har ikke spilt noen spill for på det seneste. Det er det på tide at endre på!",
|
||||
"display_name": "Brukernavn",
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
"queued": "{{title}} (Na fila)",
|
||||
"game_has_no_executable": "Jogo não possui executável selecionado",
|
||||
"sign_in": "Login",
|
||||
"friends": "Amigos"
|
||||
"friends": "Amigos",
|
||||
"need_help": "Precisa de ajuda?"
|
||||
},
|
||||
"header": {
|
||||
"search": "Buscar jogos",
|
||||
@@ -157,11 +158,13 @@
|
||||
"no_download_option_info": "Sem informações disponíveis",
|
||||
"backup_deletion_failed": "Falha ao apagar backup",
|
||||
"max_number_of_artifacts_reached": "Número máximo de backups atingido para este jogo",
|
||||
"achievements_not_sync": "Suas conquistas não estão sincronizadas",
|
||||
"achievements_not_sync": "Veja como exibir suas conquistas no perfil",
|
||||
"backup_from": "Backup de {{date}}",
|
||||
"custom_backup_location_set": "Localização customizada selecionada",
|
||||
"select_folder": "Selecione a pasta",
|
||||
"manage_files_description": "Gerencie quais arquivos serão feitos backup"
|
||||
"manage_files_description": "Gerencie quais arquivos serão feitos backup",
|
||||
"clear": "Limpar",
|
||||
"no_directory_selected": "Nenhum diretório selecionado"
|
||||
},
|
||||
"activation": {
|
||||
"title": "Ativação",
|
||||
@@ -194,7 +197,11 @@
|
||||
"queued": "Na fila",
|
||||
"no_downloads_title": "Nada por aqui…",
|
||||
"no_downloads_description": "Você ainda não baixou nada pelo Hydra, mas nunca é tarde para começar.",
|
||||
"checking_files": "Verificando arquivos…"
|
||||
"checking_files": "Verificando arquivos…",
|
||||
"seeding": "Semeando",
|
||||
"stop_seeding": "Parar de semear",
|
||||
"resume_seeding": "Semear",
|
||||
"options": "Gerenciar"
|
||||
},
|
||||
"settings": {
|
||||
"downloads_path": "Diretório dos downloads",
|
||||
@@ -250,7 +257,10 @@
|
||||
"blocked_users": "Usuários bloqueados",
|
||||
"user_unblocked": "Usuário desbloqueado",
|
||||
"enable_achievement_notifications": "Quando uma conquista é desbloqueada",
|
||||
"launch_minimized": "Iniciar o Hydra minimizado"
|
||||
"launch_minimized": "Iniciar o Hydra minimizado",
|
||||
"disable_nsfw_alert": "Desativar alerta de conteúdo inapropriado",
|
||||
"seed_after_download_complete": "Semear após a conclusão do download",
|
||||
"show_hidden_achievement_description": "Mostrar descrição de conquistas ocultas antes de debloqueá-las"
|
||||
},
|
||||
"notifications": {
|
||||
"download_complete": "Download concluído",
|
||||
@@ -274,8 +284,15 @@
|
||||
"instructions": "Verifique a forma correta de instalar algum deles no seu distro Linux, garantindo assim a execução normal do jogo"
|
||||
},
|
||||
"catalogue": {
|
||||
"next_page": "Próxima página",
|
||||
"previous_page": "Página anterior"
|
||||
"search": "Filtrar…",
|
||||
"developers": "Desenvolvedores",
|
||||
"genres": "Gêneros",
|
||||
"tags": "Marcadores",
|
||||
"publishers": "Distribuidoras",
|
||||
"download_sources": "Fontes de download",
|
||||
"result_count": "{{resultCount}} resultados",
|
||||
"filter_count": "{{filterCount}} disponíveis",
|
||||
"clear_filters": "Limpar {{filterCount}} selecionados"
|
||||
},
|
||||
"modal": {
|
||||
"close": "Botão de fechar"
|
||||
@@ -289,7 +306,7 @@
|
||||
"last_time_played": "Última sessão {{period}}",
|
||||
"activity": "Atividades recentes",
|
||||
"library": "Biblioteca",
|
||||
"total_play_time": "Tempo total de jogo: {{amount}}",
|
||||
"total_play_time": "Tempo total de jogo",
|
||||
"no_recent_activity_title": "Hmmm… nada por aqui",
|
||||
"no_recent_activity_description": "Parece que você não jogou nada recentemente. Que tal começar agora?",
|
||||
"display_name": "Nome de exibição",
|
||||
@@ -352,24 +369,43 @@
|
||||
"your_friend_code": "Seu código de amigo:",
|
||||
"upload_banner": "Carregar banner",
|
||||
"uploading_banner": "Carregando banner…",
|
||||
"background_image_updated": "Imagem de fundo salva"
|
||||
"background_image_updated": "Imagem de fundo salva",
|
||||
"stats": "Estatísticas",
|
||||
"achievements": "conquistas",
|
||||
"games": "Jogos",
|
||||
"ranking_updated_weekly": "O ranking é atualizado semanalmente",
|
||||
"playing": "Jogando {{game}}",
|
||||
"achievements_unlocked": "Conquistas desbloqueadas",
|
||||
"earned_points": "Pontos ganhos",
|
||||
"show_achievements_on_profile": "Exiba suas conquistas no perfil",
|
||||
"show_points_on_profile": "Exiba seus pontos ganhos no perfil"
|
||||
},
|
||||
"achievement": {
|
||||
"achievement_unlocked": "Conquista desbloqueada",
|
||||
"your_achievements": "Suas Conquistas",
|
||||
"user_achievements": "Conquistas de {{displayName}}",
|
||||
"unlocked_at": "Desbloqueado em:",
|
||||
"unlocked_at": "Desbloqueada em: {{date}}",
|
||||
"subscription_needed": "Você precisa de uma assinatura Hydra Cloud para visualizar este conteúdo",
|
||||
"new_achievements_unlocked": "{{achievementCount}} novas conquistas de {{gameCount}} jogos"
|
||||
"new_achievements_unlocked": "{{achievementCount}} novas conquistas de {{gameCount}} jogos",
|
||||
"achievement_progress": "{{unlockedCount}}/{{totalCount}} conquistas",
|
||||
"achievements_unlocked_for_game": "Desbloqueadas {{achievementCount}} novas conquistas em {{gameTitle}}",
|
||||
"hidden_achievement_tooltip": "Está é uma conquista oculta",
|
||||
"achievement_earn_points": "Ganhe {{points}} pontos com essa conquista",
|
||||
"earned_points": "Pontos ganhos:",
|
||||
"available_points": "Pontos disponíveis:",
|
||||
"how_to_earn_achievements_points": "Como desbloquear pontos nas conquistas?"
|
||||
},
|
||||
"tour": {
|
||||
"hydra_cloud": {
|
||||
"subscription_tour_title": "Assinatura Hydra Cloud",
|
||||
"hydra_cloud": "Hydra Cloud",
|
||||
"subscribe_now": "Inscreva-se agora",
|
||||
"cloud_achievements": "Salvamento de conquistas em nuvem",
|
||||
"animated_profile_picture": "Fotos de perfil animadas",
|
||||
"premium_support": "Suporte Premium",
|
||||
"show_and_compare_achievements": "Exiba e compare suas conquistas com outros usuários",
|
||||
"animated_profile_banner": "Banner animado no perfil",
|
||||
"cloud_saving": "Saves de jogos em nuvem"
|
||||
"cloud_saving": "Saves de jogos em nuvem",
|
||||
"hydra_cloud_feature_found": "Você descobriu uma funcionalidade Hydra Cloud!",
|
||||
"learn_more": "Saiba mais"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@
|
||||
"last_time_played": "Última sessão {{period}}",
|
||||
"activity": "Atividade recente",
|
||||
"library": "Biblioteca",
|
||||
"total_play_time": "Tempo total de jogo: {{amount}}",
|
||||
"total_play_time": "Tempo total de jogo",
|
||||
"no_recent_activity_title": "Hmmm… não há nada por aqui",
|
||||
"no_recent_activity_description": "Parece que não jogaste nada recentemente. Que tal começar agora?",
|
||||
"display_name": "Nome de apresentação",
|
||||
@@ -356,11 +356,11 @@
|
||||
"achievement_unlocked": "Conquista desbloqueada",
|
||||
"your_achievements": "As tuas Conquistas",
|
||||
"user_achievements": "Conquistas de {{displayName}}",
|
||||
"unlocked_at": "Desbloqueada em:",
|
||||
"unlocked_at": "Desbloqueada em: {{date}}",
|
||||
"subscription_needed": "Precisas de uma subscrição Hydra Cloud para visualizar este conteúdo",
|
||||
"new_achievements_unlocked": "{{achievementCount}} novas conquistas de {{gameCount}} jogos"
|
||||
},
|
||||
"tour": {
|
||||
"hydra_cloud": {
|
||||
"subscription_tour_title": "Subscrição Hydra Cloud",
|
||||
"subscribe_now": "Subscreve agora",
|
||||
"cloud_achievements": "Gravação de conquistas na nuvem",
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
"successfully_signed_in": "Успешный вход"
|
||||
},
|
||||
"home": {
|
||||
"featured": "Рекомендованное",
|
||||
"featured": "Рекомендации",
|
||||
"surprise_me": "Удиви меня",
|
||||
"no_results": "Ничего не найдено",
|
||||
"hot": "Сейчас жарко",
|
||||
"hot": "Сейчас в топе",
|
||||
"start_typing": "Начинаю вводить текст для поиска...",
|
||||
"weekly": "📅 Лучшие игры недели"
|
||||
"weekly": "📅 Лучшие игры недели",
|
||||
"achievements": "🏆 Игры, в которых нужно победить"
|
||||
},
|
||||
"sidebar": {
|
||||
"catalogue": "Каталог",
|
||||
@@ -19,12 +20,13 @@
|
||||
"downloading_metadata": "{{title}} (Загрузка метаданных…)",
|
||||
"paused": "{{title}} (Приостановлено)",
|
||||
"downloading": "{{title}} ({{percentage}} - Загрузка…)",
|
||||
"filter": "Фильтр библиотеки",
|
||||
"filter": "Поиск",
|
||||
"home": "Главная",
|
||||
"queued": "{{title}} (В очереди)",
|
||||
"game_has_no_executable": "Файл запуска игры не выбран",
|
||||
"sign_in": "Войти",
|
||||
"friends": "Друзья"
|
||||
"friends": "Друзья",
|
||||
"need_help": "Нужна помощь?"
|
||||
},
|
||||
"header": {
|
||||
"search": "Поиск",
|
||||
@@ -44,14 +46,21 @@
|
||||
"checking_files": "Проверка файлов {{title}}… ({{percentage}} завершено)"
|
||||
},
|
||||
"catalogue": {
|
||||
"next_page": "Следующая страница",
|
||||
"previous_page": "Предыдущая страница"
|
||||
"search": "Фильтр…",
|
||||
"developers": "Разработчики",
|
||||
"genres": "Жанры",
|
||||
"tags": "Маркеры",
|
||||
"publishers": "Издательства",
|
||||
"download_sources": "Источники загрузки",
|
||||
"result_count": "{{resultCount}} результатов",
|
||||
"filter_count": "{{filterCount}} доступных",
|
||||
"clear_filters": "Очистить {{filterCount}} выбранных"
|
||||
},
|
||||
"game_details": {
|
||||
"open_download_options": "Открыть варианты загрузки",
|
||||
"download_options_zero": "Нет вариантов загрузки",
|
||||
"download_options_one": "{{count}} вариант загрузки",
|
||||
"download_options_other": "{{count}} вариантов загрузки",
|
||||
"open_download_options": "Открыть источники",
|
||||
"download_options_zero": "Нет источников",
|
||||
"download_options_one": "{{count}} источник",
|
||||
"download_options_other": "{{count}} источников",
|
||||
"updated_at": "Обновлено {{updated_at}}",
|
||||
"install": "Установить",
|
||||
"resume": "Возобновить",
|
||||
@@ -62,7 +71,7 @@
|
||||
"eta": "Окончание {{eta}}",
|
||||
"calculating_eta": "Подсчёт оставшегося времени…",
|
||||
"downloading_metadata": "Загрузка метаданных…",
|
||||
"filter": "Фильтр репаков",
|
||||
"filter": "Поиск репаков",
|
||||
"requirements": "Системные требования",
|
||||
"minimum": "Минимальные",
|
||||
"recommended": "Рекомендуемые",
|
||||
@@ -76,7 +85,7 @@
|
||||
"accuracy": "точность {{accuracy}}%",
|
||||
"add_to_library": "Добавить в библиотеку",
|
||||
"remove_from_library": "Удалить из библиотеки",
|
||||
"no_downloads": "Нет доступных загрузок",
|
||||
"no_downloads": "Нет доступных источников",
|
||||
"play_time": "Сыграно {{amount}}",
|
||||
"last_time_played": "Последний запуск {{period}}",
|
||||
"not_played_yet": "Вы ещё не играли в {{title}}",
|
||||
@@ -90,7 +99,7 @@
|
||||
"select_folder_hint": "Чтобы изменить папку загрузок по умолчанию, откройте <0>Настройки</0>",
|
||||
"download_now": "Загрузить сейчас",
|
||||
"no_shop_details": "Не удалось получить описание",
|
||||
"download_options": "Вариантов загрузки",
|
||||
"download_options": "Источники",
|
||||
"download_path": "Путь для загрузок",
|
||||
"previous_screenshot": "Предыдущий скриншот",
|
||||
"next_screenshot": "Следующий скриншот",
|
||||
@@ -103,6 +112,7 @@
|
||||
"open_folder": "Открыть папку",
|
||||
"open_download_location": "Просмотреть папку загрузок",
|
||||
"create_shortcut": "Создать ярлык на рабочем столе",
|
||||
"clear": "Очистить",
|
||||
"remove_files": "Удалить файлы",
|
||||
"remove_from_library_title": "Вы уверены?",
|
||||
"remove_from_library_description": "{{game}} будет удалена из вашей библиотеки.",
|
||||
@@ -112,22 +122,60 @@
|
||||
"downloads_secion_title": "Загрузки",
|
||||
"downloads_section_description": "Проверить наличие обновлений или других версий игры",
|
||||
"danger_zone_section_title": "Опасная зона",
|
||||
"danger_zone_section_description": "Удалить эту игру из вашей библиотеки или файлы скачанные Hydra",
|
||||
"danger_zone_section_description": "Вы можете удалить эту игру из вашей библиотеки или файлы скачанные из Hydra",
|
||||
"download_in_progress": "Идёт загрузка",
|
||||
"download_paused": "Загрузка приостановлена",
|
||||
"last_downloaded_option": "Последний вариант загрузки",
|
||||
"create_shortcut_success": "Ярлык создан",
|
||||
"create_shortcut_error": "Не удалось создать ярлык",
|
||||
"allow_nsfw_content": "Продолжать",
|
||||
"allow_nsfw_content": "Продолжить",
|
||||
"download": "Скачать",
|
||||
"download_count": "Загрузки",
|
||||
"download_error": "Этот вариант загрузки недоступен",
|
||||
"executable_path_in_use": "Исполняемый файл уже используется \"{{game}}\"",
|
||||
"nsfw_content_description": "{{title}} содержит контент, который может не подходить для всех возрастов. \nВы уверены, что хотите продолжить?",
|
||||
"nsfw_content_title": "Эта игра содержит неприемлемый контент",
|
||||
"refuse_nsfw_content": "Назад",
|
||||
"stats": "Статистика",
|
||||
"player_count": "Активные игроки",
|
||||
"refuse_nsfw_content": "Возвращаться",
|
||||
"stats": "Статистика"
|
||||
"warning": "Внимание:",
|
||||
"hydra_needs_to_remain_open": "Для этой загрузки Hydra должна оставаться открытой до завершения. Если Hydra закроется до завершения, вы потеряете прогресс.",
|
||||
"achievements": "Достижения",
|
||||
"achievements_count": "Достижения {{unlockedCount}}/{{achievementsCount}}",
|
||||
"cloud_save": "Облачное сохранение",
|
||||
"cloud_save_description": "Сохраняйте ваш прогресс в облаке и продолжайте играть на любом устройстве",
|
||||
"backups": "Резервные копии",
|
||||
"install_backup": "Установить",
|
||||
"delete_backup": "Удалить",
|
||||
"create_backup": "Создать новую резервную копию",
|
||||
"last_backup_date": "Последняя резервная копия от {{date}}",
|
||||
"no_backup_preview": "Сохранения для этого заголовка не найдены",
|
||||
"restoring_backup": "Восстановление резервной копии ({{progress}} завершено)…",
|
||||
"uploading_backup": "Загрузка резервной копии…",
|
||||
"no_backups": "Вы еще не создали резервных копий для этой игры",
|
||||
"backup_uploaded": "Резервная копия загружена",
|
||||
"backup_deleted": "Резервная копия удалена",
|
||||
"backup_restored": "Резервная копия восстановлена",
|
||||
"see_all_achievements": "Просмотреть все достижения",
|
||||
"sign_in_to_see_achievements": "Войдите, чтобы увидеть достижения",
|
||||
"mapping_method_automatic": "Автоматическая",
|
||||
"mapping_method_manual": "Ручная",
|
||||
"mapping_method_label": "Метод сопоставления",
|
||||
"files_automatically_mapped": "Файлы автоматически сопоставлены",
|
||||
"no_backups_created": "Для этой игры не создано резервных копий",
|
||||
"manage_files": "Управление файлами",
|
||||
"loading_save_preview": "Поиск сохранений…",
|
||||
"wine_prefix": "Префикс Wine",
|
||||
"wine_prefix_description": "Префикс Wine, используемый для запуска этой игры",
|
||||
"no_download_option_info": "Информация недоступна",
|
||||
"backup_deletion_failed": "Не удалось удалить резервную копию",
|
||||
"max_number_of_artifacts_reached": "Достигнуто максимальное количество резервных копий для этой игры",
|
||||
"achievements_not_sync": "Ваши достижения не синхронизированы",
|
||||
"manage_files_description": "Управляйте файлами, которые будут сохраняться и восстанавливаться",
|
||||
"select_folder": "Выбрать папку",
|
||||
"backup_from": "Резервная копия от {{date}}",
|
||||
"custom_backup_location_set": "Установлено настраиваемое местоположение резервной копии",
|
||||
"no_directory_selected": "Не выбран каталог"
|
||||
},
|
||||
"activation": {
|
||||
"title": "Активировать Hydra",
|
||||
@@ -146,7 +194,7 @@
|
||||
"completed": "Завершено",
|
||||
"removed": "Не скачано",
|
||||
"cancel": "Отмена",
|
||||
"filter": "Фильтр загруженных игр",
|
||||
"filter": "Поиск загруженных игр",
|
||||
"remove": "Удалить",
|
||||
"downloading_metadata": "Загрузка метаданных…",
|
||||
"deleting": "Удаление установщика…",
|
||||
@@ -160,17 +208,24 @@
|
||||
"queued": "В очереди",
|
||||
"no_downloads_title": "Здесь так пусто...",
|
||||
"no_downloads_description": "Вы ещё ничего не скачали через Hydra, но никогда не поздно начать.",
|
||||
"checking_files": "Проверка файлов…"
|
||||
"checking_files": "Проверка файлов…",
|
||||
"seeding": "Раздача",
|
||||
"stop_seeding": "Остановить раздачу",
|
||||
"resume_seeding": "Продолжить раздачу",
|
||||
"options": "Управлять"
|
||||
},
|
||||
"settings": {
|
||||
"downloads_path": "Путь загрузок",
|
||||
"change": "Изменить",
|
||||
"notifications": "Уведомления",
|
||||
"enable_download_notifications": "По завершении загрузки",
|
||||
"enable_achievement_notifications": "Когда достижение разблокировано",
|
||||
"enable_repack_list_notifications": "При добавлении нового репака",
|
||||
"real_debrid_api_token_label": "Real-Debrid API-токен",
|
||||
"quit_app_instead_hiding": "Закрывать приложение вместо сворачивания в трей",
|
||||
"launch_with_system": "Запускать Hydra вместе с системой",
|
||||
"launch_minimized": "Запустить Hydra в свернутом виде",
|
||||
"disable_nsfw_alert": "Отключить предупреждение о непристойном контенте",
|
||||
"general": "Основные",
|
||||
"behavior": "Поведение",
|
||||
"download_sources": "Источники загрузки",
|
||||
@@ -195,7 +250,7 @@
|
||||
"add_download_source_description": "Вставьте ссылку на .json-файл",
|
||||
"download_source_up_to_date": "Обновлён",
|
||||
"download_source_errored": "Ошибка",
|
||||
"sync_download_sources": "Синхронизировать источники",
|
||||
"sync_download_sources": "Обновить источники",
|
||||
"removed_download_source": "Источник загрузок удален",
|
||||
"added_download_source": "Источник загрузок добавлен",
|
||||
"download_sources_synced": "Все источники загрузок синхронизированы",
|
||||
@@ -205,16 +260,18 @@
|
||||
"found_download_option_other": "Найдено {{countFormatted}} вариантов загрузки",
|
||||
"import": "Импортировать",
|
||||
"blocked_users": "Заблокированные пользователи",
|
||||
"friends_only": "Только друзья",
|
||||
"friends_only": "Только для друзей",
|
||||
"must_be_valid_url": "Источник должен быть действительным URL-адресом.",
|
||||
"privacy": "Конфиденциальность",
|
||||
"private": "Частный",
|
||||
"profile_visibility": "Видимость профиля",
|
||||
"profile_visibility_description": "Выберите, кто может видеть ваш профиль и библиотеку",
|
||||
"public": "Общественный",
|
||||
"public": "Публичный",
|
||||
"required_field": "Это поле обязательно к заполнению",
|
||||
"source_already_exists": "Этот источник уже добавлен",
|
||||
"user_unblocked": "Пользователь разблокирован"
|
||||
"user_unblocked": "Пользователь разблокирован",
|
||||
"seed_after_download_complete": "Раздавать после завершения загрузки",
|
||||
"show_hidden_achievement_description": "Показывать описание скрытых достижений перед их получением"
|
||||
},
|
||||
"notifications": {
|
||||
"download_complete": "Загрузка завершена",
|
||||
@@ -222,15 +279,17 @@
|
||||
"repack_list_updated": "Список репаков обновлен",
|
||||
"repack_count_one": "{{count}} репак добавлен",
|
||||
"repack_count_other": "{{count}} репаков добавлено",
|
||||
"new_update_available": "Доступна версия {{version}}",
|
||||
"restart_to_install_update": "Перезапустите Hydra для установки обновления"
|
||||
"new_update_available": "Доступна новая версия {{version}}",
|
||||
"restart_to_install_update": "Перезапустите Hydra для установки обновления",
|
||||
"notification_achievement_unlocked_title": "Достижение разблокировано для {{game}}",
|
||||
"notification_achievement_unlocked_body": "были разблокированы {{achievement}} и другие {{count}}"
|
||||
},
|
||||
"system_tray": {
|
||||
"open": "Открыть Hydra",
|
||||
"quit": "Выйти"
|
||||
},
|
||||
"game_card": {
|
||||
"no_downloads": "Нет доступных загрузок"
|
||||
"no_downloads": "Нет доступных источников"
|
||||
},
|
||||
"binary_not_found_modal": {
|
||||
"title": "Программы не установлены",
|
||||
@@ -249,7 +308,7 @@
|
||||
"last_time_played": "Последняя игра {{period}}",
|
||||
"activity": "Недавняя активность",
|
||||
"library": "Библиотека",
|
||||
"total_play_time": "Всего сыграно: {{amount}}",
|
||||
"total_play_time": "Всего сыграно",
|
||||
"no_recent_activity_title": "Хммм... Тут ничего нет",
|
||||
"no_recent_activity_description": "Вы давно ни во что не играли. Пора это изменить!",
|
||||
"display_name": "Отображаемое имя",
|
||||
@@ -308,6 +367,46 @@
|
||||
"report_reason_spam": "Спам",
|
||||
"report_reason_violence": "Насилие",
|
||||
"required_field": "Это поле обязательно к заполнению",
|
||||
"undo_friendship_modal_text": "Это отменит вашу дружбу с {{displayName}}."
|
||||
"undo_friendship_modal_text": "Это отменит вашу дружбу с {{displayName}}.",
|
||||
"your_friend_code": "Код вашего друга:",
|
||||
"upload_banner": "Загрузить баннер",
|
||||
"uploading_banner": "Загрузка баннера...",
|
||||
"background_image_updated": "Фоновое изображение обновлено",
|
||||
"stats": "Статистика",
|
||||
"games": "Игры",
|
||||
"top_percentile": "Топ {{percentile}}%",
|
||||
"ranking_updated_weekly": "Рейтинг обновляется еженедельно",
|
||||
"playing": "Играет в {{game}}",
|
||||
"achievements_unlocked": "Достижения разблокированы",
|
||||
"show_achievements_on_profile": "Покажите свои достижения в профиле",
|
||||
"show_points_on_profile": "Показывать заработанные очки в своем профиле"
|
||||
},
|
||||
"achievement": {
|
||||
"achievement_unlocked": "Достижение разблокировано",
|
||||
"user_achievements": "Достижения {{displayName}}",
|
||||
"your_achievements": "Ваши достижения",
|
||||
"unlocked_at": "Разблокировано: {{date}}",
|
||||
"subscription_needed": "Для просмотра этого содержимого необходима подписка на Hydra Cloud",
|
||||
"new_achievements_unlocked": "Разблокировано {{achievementCount}} новых достижений из {{gameCount}} игр",
|
||||
"achievement_progress": "{{unlockedCount}}/{{totalCount}} достижений",
|
||||
"achievements_unlocked_for_game": "Разблокировано {{achievementCount}} новых достижений для {{gameTitle}}",
|
||||
"hidden_achievement_tooltip": "Это скрытое достижение",
|
||||
"achievement_earn_points": "Заработайте {{points}} очков с этим достижением",
|
||||
"earned_points": "Заработано очков:",
|
||||
"available_points": "Доступные очки:",
|
||||
"how_to_earn_achievements_points": "Как заработать очки достижений?"
|
||||
},
|
||||
"hydra_cloud": {
|
||||
"subscription_tour_title": "Подписка Hydra Cloud",
|
||||
"subscribe_now": "Подпишитесь прямо сейчас",
|
||||
"cloud_saving": "Сохранение в облаке",
|
||||
"cloud_achievements": "Сохраняйте свои достижения в облаке",
|
||||
"animated_profile_picture": "Анимированные фотографии профиля",
|
||||
"premium_support": "Премиальная поддержка",
|
||||
"show_and_compare_achievements": "Показывайте и сравнивайте свои достижения с достижениями других пользователей",
|
||||
"animated_profile_banner": "Анимированный баннер профиля",
|
||||
"hydra_cloud": "Hydra Cloud",
|
||||
"hydra_cloud_feature_found": "Вы только что открыли для себя функцию Hydra Cloud!",
|
||||
"learn_more": "Подробнее"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
"sign_out_modal_text": "Ваша бібліотека пов'язана з поточним обліковим записом. При виході з системи ваша бібліотека буде недоступною, і прогрес не буде збережено. Продовжити вихід?",
|
||||
"sign_out_modal_title": "Ви впевнені?",
|
||||
"successfully_signed_out": "Успішний вихід з акаунту",
|
||||
"total_play_time": "Всього зіграно: {{amount}}",
|
||||
"total_play_time": "Всього зіграно",
|
||||
"try_again": "Будь ласка, попробуйте ще раз"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@
|
||||
"last_time_played": "上次游玩时间 {{period}}",
|
||||
"activity": "近期活动",
|
||||
"library": "库",
|
||||
"total_play_time": "总游戏时长: {{amount}}",
|
||||
"total_play_time": "总游戏时长",
|
||||
"no_recent_activity_title": "Emmm… 这里暂时啥都没有",
|
||||
"no_recent_activity_description": "你最近没玩过任何游戏。是时候做出改变了!",
|
||||
"display_name": "昵称",
|
||||
@@ -359,11 +359,11 @@
|
||||
"achievement_unlocked": "成就已解锁",
|
||||
"user_achievements": "{{displayName}}的成就",
|
||||
"your_achievements": "你的成就",
|
||||
"unlocked_at": "解锁于:",
|
||||
"unlocked_at": "解锁于: {{date}}",
|
||||
"subscription_needed": "需要订阅 Hydra Cloud 才能看到此内容",
|
||||
"new_achievements_unlocked": "从 {{gameCount}} 游戏中解锁 {{achievementCount}} 新成就"
|
||||
},
|
||||
"tour": {
|
||||
"hydra_cloud": {
|
||||
"subscription_tour_title": "Hydra 云订阅",
|
||||
"subscribe_now": "现在订购",
|
||||
"cloud_saving": "云存档",
|
||||
|
||||
@@ -5,12 +5,12 @@ export const LUDUSAVI_MANIFEST_URL = "https://cdn.losbroxas.org/manifest.yaml";
|
||||
|
||||
export const defaultDownloadsPath = app.getPath("downloads");
|
||||
|
||||
export const isStaging = import.meta.env.MAIN_VITE_API_URL.includes("staging");
|
||||
|
||||
export const databaseDirectory = path.join(app.getPath("appData"), "hydra");
|
||||
export const databasePath = path.join(
|
||||
databaseDirectory,
|
||||
import.meta.env.MAIN_VITE_API_URL.includes("staging")
|
||||
? "hydra_test.db"
|
||||
: "hydra.db"
|
||||
isStaging ? "hydra_test.db" : "hydra.db"
|
||||
);
|
||||
|
||||
export const logsPath = path.join(app.getPath("appData"), "hydra", "logs");
|
||||
@@ -19,6 +19,10 @@ export const seedsPath = app.isPackaged
|
||||
? path.join(process.resourcesPath, "seeds")
|
||||
: path.join(__dirname, "..", "..", "seeds");
|
||||
|
||||
export const achievementSoundPath = app.isPackaged
|
||||
? path.join(process.resourcesPath, "achievement.wav")
|
||||
: path.join(__dirname, "..", "..", "resources", "achievement.wav");
|
||||
|
||||
export const backupsPath = path.join(app.getPath("userData"), "Backups");
|
||||
|
||||
export const appVersion = app.getVersion();
|
||||
export const appVersion = app.getVersion() + (isStaging ? "-staging" : "");
|
||||
|
||||
@@ -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,19 +70,15 @@ export class Game {
|
||||
@Column("text", { nullable: true })
|
||||
uri: string | null;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@OneToOne("Repack", "game", { nullable: true })
|
||||
@JoinColumn()
|
||||
repack: Repack;
|
||||
|
||||
@OneToOne("DownloadQueue", "game")
|
||||
downloadQueue: DownloadQueue;
|
||||
|
||||
@Column("boolean", { default: false })
|
||||
isDeleted: boolean;
|
||||
|
||||
@Column("boolean", { default: false })
|
||||
shouldSeed: boolean;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt: Date;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -38,6 +38,15 @@ export class UserPreferences {
|
||||
@Column("boolean", { default: false })
|
||||
startMinimized: boolean;
|
||||
|
||||
@Column("boolean", { default: false })
|
||||
disableNsfwAlert: boolean;
|
||||
|
||||
@Column("boolean", { default: true })
|
||||
seedAfterDownloadComplete: boolean;
|
||||
|
||||
@Column("boolean", { default: false })
|
||||
showHiddenAchievementsDescription: boolean;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt: Date;
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import jwt from "jsonwebtoken";
|
||||
import * as Sentry from "@sentry/electron/main";
|
||||
|
||||
import { userAuthRepository } from "@main/repository";
|
||||
import { registerEvent } from "../register-event";
|
||||
@@ -10,8 +9,6 @@ const getSessionHash = async (_event: Electron.IpcMainInvokeEvent) => {
|
||||
if (!auth) return null;
|
||||
const payload = jwt.decode(auth.accessToken) as jwt.JwtPayload;
|
||||
|
||||
Sentry.setContext("sessionId", payload.sessionId);
|
||||
|
||||
return payload.sessionId;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import * as Sentry from "@sentry/electron/main";
|
||||
import {
|
||||
DownloadManager,
|
||||
HydraApi,
|
||||
PythonInstance,
|
||||
gamesPlaytime,
|
||||
} from "@main/services";
|
||||
import { DownloadManager, HydraApi, gamesPlaytime } from "@main/services";
|
||||
import { dataSource } from "@main/data-source";
|
||||
import { DownloadQueue, Game, UserAuth, UserSubscription } from "@main/entity";
|
||||
import { PythonRPC } from "@main/services/python-rpc";
|
||||
|
||||
const signOut = async (_event: Electron.IpcMainInvokeEvent) => {
|
||||
const databaseOperations = dataSource
|
||||
@@ -29,14 +24,11 @@ const signOut = async (_event: Electron.IpcMainInvokeEvent) => {
|
||||
gamesPlaytime.clear();
|
||||
});
|
||||
|
||||
/* Removes user from Sentry */
|
||||
Sentry.setUser(null);
|
||||
|
||||
/* Cancels any ongoing downloads */
|
||||
DownloadManager.cancelDownload();
|
||||
|
||||
/* Disconnects libtorrent */
|
||||
PythonInstance.killTorrent();
|
||||
PythonRPC.kill();
|
||||
|
||||
HydraApi.handleSignOut();
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
@@ -1,23 +1,21 @@
|
||||
import type { HowLongToBeatCategory } from "@types";
|
||||
import { getHowLongToBeatGame, searchHowLongToBeat } from "@main/services";
|
||||
import type { GameShop, HowLongToBeatCategory } from "@types";
|
||||
|
||||
import { registerEvent } from "../register-event";
|
||||
import { formatName } from "@shared";
|
||||
import { HydraApi } from "@main/services";
|
||||
|
||||
const getHowLongToBeat = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
title: string
|
||||
objectId: string,
|
||||
shop: GameShop
|
||||
): Promise<HowLongToBeatCategory[] | null> => {
|
||||
const response = await searchHowLongToBeat(title);
|
||||
|
||||
const game = response.data.find((game) => {
|
||||
return formatName(game.game_name) === formatName(title);
|
||||
const params = new URLSearchParams({
|
||||
objectId,
|
||||
shop,
|
||||
});
|
||||
|
||||
if (!game) return null;
|
||||
const howLongToBeat = await getHowLongToBeatGame(String(game.game_id));
|
||||
|
||||
return howLongToBeat;
|
||||
return HydraApi.get(`/games/how-long-to-beat?${params.toString()}`, null, {
|
||||
needsAuth: false,
|
||||
});
|
||||
};
|
||||
|
||||
registerEvent("getHowLongToBeat", getHowLongToBeat);
|
||||
|
||||
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,18 @@
|
||||
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,
|
||||
take: number,
|
||||
skip: number
|
||||
) => {
|
||||
return HydraApi.post(
|
||||
"/catalogue/search",
|
||||
{ ...payload, take, skip },
|
||||
{ needsAuth: false }
|
||||
);
|
||||
};
|
||||
|
||||
registerEvent("searchGames", searchGamesEvent);
|
||||
registerEvent("searchGames", searchGames);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { HydraApi } from "@main/services";
|
||||
import { registerEvent } from "../register-event";
|
||||
import type { GameArtifact, GameShop } from "@types";
|
||||
import { SubscriptionRequiredError } from "@shared";
|
||||
|
||||
const getGameArtifacts = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
@@ -13,8 +14,16 @@ const getGameArtifacts = async (
|
||||
});
|
||||
|
||||
return HydraApi.get<GameArtifact[]>(
|
||||
`/profile/games/artifacts?${params.toString()}`
|
||||
);
|
||||
`/profile/games/artifacts?${params.toString()}`,
|
||||
{},
|
||||
{ needsSubscription: true }
|
||||
).catch((err) => {
|
||||
if (err instanceof SubscriptionRequiredError) {
|
||||
return [];
|
||||
}
|
||||
|
||||
throw err;
|
||||
});
|
||||
};
|
||||
|
||||
registerEvent("getGameArtifacts", getGameArtifacts);
|
||||
|
||||
@@ -89,7 +89,7 @@ const uploadSaveGame = async (
|
||||
"Content-Type": "application/tar",
|
||||
},
|
||||
onUploadProgress: (progressEvent) => {
|
||||
console.log(progressEvent);
|
||||
logger.log(progressEvent);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
};
|
||||
@@ -1,14 +1,15 @@
|
||||
import { appVersion, defaultDownloadsPath } from "@main/constants";
|
||||
import { appVersion, defaultDownloadsPath, isStaging } from "@main/constants";
|
||||
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";
|
||||
@@ -32,14 +33,15 @@ import "./torrenting/cancel-game-download";
|
||||
import "./torrenting/pause-game-download";
|
||||
import "./torrenting/resume-game-download";
|
||||
import "./torrenting/start-game-download";
|
||||
import "./torrenting/pause-game-seed";
|
||||
import "./torrenting/resume-game-seed";
|
||||
import "./user-preferences/get-user-preferences";
|
||||
import "./user-preferences/update-user-preferences";
|
||||
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";
|
||||
@@ -72,5 +74,6 @@ import "./misc/show-item-in-folder";
|
||||
|
||||
ipcMain.handle("ping", () => "pong");
|
||||
ipcMain.handle("getVersion", () => appVersion);
|
||||
ipcMain.handle("isStaging", () => isStaging);
|
||||
ipcMain.handle("isPortableVersion", () => isPortableVersion());
|
||||
ipcMain.handle("getDefaultDownloadsPath", () => defaultDownloadsPath);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { gameRepository } from "@main/repository";
|
||||
import { registerEvent } from "../register-event";
|
||||
import { PythonInstance, logger } from "@main/services";
|
||||
import { logger } from "@main/services";
|
||||
import sudo from "sudo-prompt";
|
||||
import { app } from "electron";
|
||||
import { PythonRPC } from "@main/services/python-rpc";
|
||||
import { ProcessPayload } from "@main/services/download/types";
|
||||
|
||||
const getKillCommand = (pid: number) => {
|
||||
if (process.platform == "win32") {
|
||||
@@ -16,7 +18,10 @@ const closeGame = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
gameId: number
|
||||
) => {
|
||||
const processes = await PythonInstance.getProcessList();
|
||||
const processes =
|
||||
(await PythonRPC.rpc.get<ProcessPayload[] | null>("/process-list")).data ||
|
||||
[];
|
||||
|
||||
const game = await gameRepository.findOne({
|
||||
where: { id: gameId, isDeleted: false },
|
||||
});
|
||||
@@ -24,7 +29,11 @@ const closeGame = async (
|
||||
if (!game) return;
|
||||
|
||||
const gameProcess = processes.find((runningProcess) => {
|
||||
return runningProcess.exe === game.executablePath;
|
||||
if (process.platform === "linux") {
|
||||
return runningProcess.name === game.executablePath?.split("/").at(-1);
|
||||
} else {
|
||||
return runningProcess.exe === game.executablePath;
|
||||
}
|
||||
});
|
||||
|
||||
if (gameProcess) {
|
||||
|
||||
@@ -5,9 +5,9 @@ import { registerEvent } from "../register-event";
|
||||
const selectGameWinePrefix = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
id: number,
|
||||
winePrefixPath: string
|
||||
winePrefixPath: string | null
|
||||
) => {
|
||||
return gameRepository.update({ id }, { winePrefixPath });
|
||||
return gameRepository.update({ id }, { winePrefixPath: winePrefixPath });
|
||||
};
|
||||
|
||||
registerEvent("selectGameWinePrefix", selectGameWinePrefix);
|
||||
|
||||
@@ -6,14 +6,18 @@ import { parseExecutablePath } from "../helpers/parse-executable-path";
|
||||
const updateExecutablePath = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
id: number,
|
||||
executablePath: string
|
||||
executablePath: string | null
|
||||
) => {
|
||||
const parsedPath = executablePath
|
||||
? parseExecutablePath(executablePath)
|
||||
: null;
|
||||
|
||||
return gameRepository.update(
|
||||
{
|
||||
id,
|
||||
},
|
||||
{
|
||||
executablePath: parseExecutablePath(executablePath),
|
||||
executablePath: parsedPath,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import { shell } from "electron";
|
||||
import { registerEvent } from "../register-event";
|
||||
import { userAuthRepository } from "@main/repository";
|
||||
import {
|
||||
userAuthRepository,
|
||||
userPreferencesRepository,
|
||||
} from "@main/repository";
|
||||
import { HydraApi } from "@main/services";
|
||||
|
||||
const openCheckout = async (_event: Electron.IpcMainInvokeEvent) => {
|
||||
const userAuth = await userAuthRepository.findOne({ where: { id: 1 } });
|
||||
const [userAuth, userPreferences] = await Promise.all([
|
||||
userAuthRepository.findOne({ where: { id: 1 } }),
|
||||
userPreferencesRepository.findOne({ where: { id: 1 } }),
|
||||
]);
|
||||
|
||||
if (!userAuth) {
|
||||
return;
|
||||
@@ -16,6 +22,7 @@ const openCheckout = async (_event: Electron.IpcMainInvokeEvent) => {
|
||||
|
||||
const params = new URLSearchParams({
|
||||
token: paymentToken,
|
||||
lng: userPreferences?.language || "en",
|
||||
});
|
||||
|
||||
shell.openExternal(
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import { PythonInstance } from "@main/services";
|
||||
import { PythonRPC } from "@main/services/python-rpc";
|
||||
|
||||
const processProfileImage = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
path: string
|
||||
) => {
|
||||
return PythonInstance.processProfileImage(path);
|
||||
return PythonRPC.rpc
|
||||
.post<{
|
||||
imagePath: string;
|
||||
mimeType: string;
|
||||
}>("/profile-image", { image_path: path })
|
||||
.then((response) => response.data);
|
||||
};
|
||||
|
||||
registerEvent("processProfileImage", processProfileImage);
|
||||
|
||||
17
src/main/events/torrenting/pause-game-seed.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import { DownloadManager } from "@main/services";
|
||||
import { gameRepository } from "@main/repository";
|
||||
|
||||
const pauseGameSeed = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
gameId: number
|
||||
) => {
|
||||
await gameRepository.update(gameId, {
|
||||
status: "complete",
|
||||
shouldSeed: false,
|
||||
});
|
||||
|
||||
await DownloadManager.pauseSeeding(gameId);
|
||||
};
|
||||
|
||||
registerEvent("pauseGameSeed", pauseGameSeed);
|
||||
29
src/main/events/torrenting/resume-game-seed.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import { gameRepository } from "../../repository";
|
||||
import { DownloadManager } from "@main/services";
|
||||
import { Downloader } from "@shared";
|
||||
|
||||
const resumeGameSeed = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
gameId: number
|
||||
) => {
|
||||
const game = await gameRepository.findOne({
|
||||
where: {
|
||||
id: gameId,
|
||||
isDeleted: false,
|
||||
downloader: Downloader.Torrent,
|
||||
progress: 1,
|
||||
},
|
||||
});
|
||||
|
||||
if (!game) return;
|
||||
|
||||
await gameRepository.update(gameId, {
|
||||
status: "seeding",
|
||||
shouldSeed: true,
|
||||
});
|
||||
|
||||
await DownloadManager.resumeSeeding(game);
|
||||
};
|
||||
|
||||
registerEvent("resumeGameSeed", resumeGameSeed);
|
||||
@@ -1,7 +1,6 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
|
||||
import type { StartGameDownloadPayload } from "@types";
|
||||
import { DownloadManager, HydraApi, logger } from "@main/services";
|
||||
import { DownloadManager, HydraApi } from "@main/services";
|
||||
|
||||
import { Not } from "typeorm";
|
||||
import { steamGamesWorker } from "@main/workers";
|
||||
@@ -77,24 +76,23 @@ const startGameDownload = async (
|
||||
},
|
||||
});
|
||||
|
||||
createGame(updatedGame!).catch(() => {});
|
||||
|
||||
HydraApi.post(
|
||||
"/games/download",
|
||||
{
|
||||
objectId: updatedGame!.objectID,
|
||||
shop: updatedGame!.shop,
|
||||
},
|
||||
{ needsAuth: false }
|
||||
).catch((err) => {
|
||||
logger.error("Failed to create game download", err);
|
||||
});
|
||||
|
||||
await DownloadManager.cancelDownload(updatedGame!.id);
|
||||
await DownloadManager.startDownload(updatedGame!);
|
||||
|
||||
await downloadQueueRepository.delete({ game: { id: updatedGame!.id } });
|
||||
await downloadQueueRepository.insert({ game: { id: updatedGame!.id } });
|
||||
|
||||
await Promise.all([
|
||||
createGame(updatedGame!).catch(() => {}),
|
||||
HydraApi.post(
|
||||
"/games/download",
|
||||
{
|
||||
objectId: updatedGame!.objectID,
|
||||
shop: updatedGame!.shop,
|
||||
},
|
||||
{ needsAuth: false }
|
||||
).catch(() => {}),
|
||||
]);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RealDebridClient } from "@main/services/real-debrid";
|
||||
import { RealDebridClient } from "@main/services/download/real-debrid";
|
||||
import { registerEvent } from "../register-event";
|
||||
|
||||
const authenticateRealDebrid = async (
|
||||
|
||||
@@ -13,6 +13,9 @@ const getComparedUnlockedAchievements = async (
|
||||
where: { id: 1 },
|
||||
});
|
||||
|
||||
const showHiddenAchievementsDescription =
|
||||
userPreferences?.showHiddenAchievementsDescription || false;
|
||||
|
||||
return HydraApi.get<ComparedAchievements>(
|
||||
`/users/${userId}/games/achievements/compare`,
|
||||
{
|
||||
@@ -21,15 +24,35 @@ const getComparedUnlockedAchievements = async (
|
||||
language: userPreferences?.language || "en",
|
||||
}
|
||||
).then((achievements) => {
|
||||
const sortedAchievements = achievements.achievements.sort((a, b) => {
|
||||
if (a.targetStat.unlocked && !b.targetStat.unlocked) return -1;
|
||||
if (!a.targetStat.unlocked && b.targetStat.unlocked) return 1;
|
||||
if (a.targetStat.unlocked && b.targetStat.unlocked) {
|
||||
return b.targetStat.unlockTime! - a.targetStat.unlockTime!;
|
||||
}
|
||||
const sortedAchievements = achievements.achievements
|
||||
.sort((a, b) => {
|
||||
if (a.targetStat.unlocked && !b.targetStat.unlocked) return -1;
|
||||
if (!a.targetStat.unlocked && b.targetStat.unlocked) return 1;
|
||||
if (a.targetStat.unlocked && b.targetStat.unlocked) {
|
||||
return b.targetStat.unlockTime! - a.targetStat.unlockTime!;
|
||||
}
|
||||
|
||||
return Number(a.hidden) - Number(b.hidden);
|
||||
});
|
||||
return Number(a.hidden) - Number(b.hidden);
|
||||
})
|
||||
.map((achievement) => {
|
||||
if (!achievement.hidden) return achievement;
|
||||
|
||||
if (!achievement.ownerStat) {
|
||||
return {
|
||||
...achievement,
|
||||
description: "",
|
||||
};
|
||||
}
|
||||
|
||||
if (!showHiddenAchievementsDescription && achievement.hidden) {
|
||||
return {
|
||||
...achievement,
|
||||
description: "",
|
||||
};
|
||||
}
|
||||
|
||||
return achievement;
|
||||
});
|
||||
|
||||
return {
|
||||
...achievements,
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import type { GameShop, UnlockedAchievement, UserAchievement } from "@types";
|
||||
import { registerEvent } from "../register-event";
|
||||
import { gameAchievementRepository } from "@main/repository";
|
||||
import {
|
||||
gameAchievementRepository,
|
||||
userPreferencesRepository,
|
||||
} from "@main/repository";
|
||||
import { getGameAchievementData } from "@main/services/achievements/get-game-achievement-data";
|
||||
|
||||
export const getUnlockedAchievements = async (
|
||||
@@ -12,10 +15,17 @@ export const getUnlockedAchievements = async (
|
||||
where: { objectId, shop },
|
||||
});
|
||||
|
||||
const userPreferences = await userPreferencesRepository.findOne({
|
||||
where: { id: 1 },
|
||||
});
|
||||
|
||||
const showHiddenAchievementsDescription =
|
||||
userPreferences?.showHiddenAchievementsDescription || false;
|
||||
|
||||
const achievementsData = await getGameAchievementData(
|
||||
objectId,
|
||||
shop,
|
||||
useCachedData
|
||||
useCachedData ? cachedAchievements : null
|
||||
);
|
||||
|
||||
const unlockedAchievements = JSON.parse(
|
||||
@@ -50,6 +60,10 @@ export const getUnlockedAchievements = async (
|
||||
unlocked: false,
|
||||
unlockTime: null,
|
||||
icongray: icongray,
|
||||
description:
|
||||
!achievementData.hidden || showHiddenAchievementsDescription
|
||||
? achievementData.description
|
||||
: undefined,
|
||||
} as UserAchievement;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
|
||||
@@ -11,7 +11,7 @@ const getSteamGame = async (objectId: string) => {
|
||||
});
|
||||
|
||||
return {
|
||||
title: steamGame.name,
|
||||
title: steamGame.name as string,
|
||||
iconUrl: steamUrlBuilder.icon(objectId, steamGame.clientIcon),
|
||||
};
|
||||
} catch (err) {
|
||||
@@ -67,8 +67,25 @@ const getUser = async (
|
||||
}
|
||||
}
|
||||
|
||||
const friends = await Promise.all(
|
||||
profile.friends.map(async (friend) => {
|
||||
if (!friend.currentGame) return friend;
|
||||
|
||||
const currentGame = await getSteamGame(friend.currentGame.objectId);
|
||||
|
||||
return {
|
||||
...friend,
|
||||
currentGame: {
|
||||
...friend.currentGame,
|
||||
...currentGame,
|
||||
},
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
return {
|
||||
...profile,
|
||||
friends,
|
||||
libraryGames,
|
||||
recentGames,
|
||||
};
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { app, BrowserWindow, net, protocol } from "electron";
|
||||
import { init } from "@sentry/electron/main";
|
||||
import updater from "electron-updater";
|
||||
import i18n from "i18next";
|
||||
import path from "node:path";
|
||||
import url from "node:url";
|
||||
import fs from "node:fs";
|
||||
import { electronApp, optimizer } from "@electron-toolkit/utils";
|
||||
import { logger, PythonInstance, WindowManager } from "@main/services";
|
||||
import { logger, WindowManager } from "@main/services";
|
||||
import { dataSource } from "@main/data-source";
|
||||
import resources from "@locales";
|
||||
import { userPreferencesRepository } from "@main/repository";
|
||||
import { knexClient, migrationConfig } from "./knex-client";
|
||||
import { databaseDirectory } from "./constants";
|
||||
import { PythonRPC } from "./services/python-rpc";
|
||||
import { Aria2 } from "./services/aria2";
|
||||
|
||||
const { autoUpdater } = updater;
|
||||
|
||||
@@ -26,12 +27,6 @@ autoUpdater.logger = logger;
|
||||
const gotTheLock = app.requestSingleInstanceLock();
|
||||
if (!gotTheLock) app.quit();
|
||||
|
||||
if (import.meta.env.MAIN_VITE_SENTRY_DSN) {
|
||||
init({
|
||||
dsn: import.meta.env.MAIN_VITE_SENTRY_DSN,
|
||||
});
|
||||
}
|
||||
|
||||
app.commandLine.appendSwitch("--no-sandbox");
|
||||
|
||||
i18n.init({
|
||||
@@ -105,7 +100,6 @@ app.whenReady().then(async () => {
|
||||
WindowManager.createMainWindow();
|
||||
}
|
||||
|
||||
WindowManager.createNotificationWindow();
|
||||
WindowManager.createSystemTray(userPreferences?.language || "en");
|
||||
});
|
||||
|
||||
@@ -154,7 +148,8 @@ app.on("window-all-closed", () => {
|
||||
|
||||
app.on("before-quit", () => {
|
||||
/* Disconnects libtorrent */
|
||||
PythonInstance.kill();
|
||||
PythonRPC.kill();
|
||||
Aria2.kill();
|
||||
});
|
||||
|
||||
app.on("activate", () => {
|
||||
|
||||
@@ -12,6 +12,11 @@ import { CreateUserSubscription } from "./migrations/20241015235142_create_user_
|
||||
import { AddBackgroundImageUrl } from "./migrations/20241016100249_add_background_image_url";
|
||||
import { AddWinePrefixToGame } from "./migrations/20241019081648_add_wine_prefix_to_game";
|
||||
import { AddStartMinimizedColumn } from "./migrations/20241030171454_add_start_minimized_column";
|
||||
import { AddDisableNsfwAlertColumn } from "./migrations/20241106053733_add_disable_nsfw_alert_column";
|
||||
import { AddShouldSeedColumn } from "./migrations/20241108200154_add_should_seed_colum";
|
||||
import { AddSeedAfterDownloadColumn } from "./migrations/20241108201806_add_seed_after_download";
|
||||
import { AddHiddenAchievementDescriptionColumn } from "./migrations/20241216140633_add_hidden_achievement_description_column ";
|
||||
|
||||
export type HydraMigration = Knex.Migration & { name: string };
|
||||
|
||||
class MigrationSource implements Knex.MigrationSource<HydraMigration> {
|
||||
@@ -28,6 +33,10 @@ class MigrationSource implements Knex.MigrationSource<HydraMigration> {
|
||||
AddBackgroundImageUrl,
|
||||
AddWinePrefixToGame,
|
||||
AddStartMinimizedColumn,
|
||||
AddDisableNsfwAlertColumn,
|
||||
AddShouldSeedColumn,
|
||||
AddSeedAfterDownloadColumn,
|
||||
AddHiddenAchievementDescriptionColumn,
|
||||
]);
|
||||
}
|
||||
getMigrationName(migration: HydraMigration): string {
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
import {
|
||||
DownloadManager,
|
||||
Ludusavi,
|
||||
PythonInstance,
|
||||
startMainLoop,
|
||||
} from "./services";
|
||||
import { DownloadManager, Ludusavi, startMainLoop } from "./services";
|
||||
import {
|
||||
downloadQueueRepository,
|
||||
gameRepository,
|
||||
userPreferencesRepository,
|
||||
} from "./repository";
|
||||
import { UserPreferences } from "./entity";
|
||||
import { RealDebridClient } from "./services/real-debrid";
|
||||
import { RealDebridClient } from "./services/download/real-debrid";
|
||||
import { HydraApi } from "./services/hydra-api";
|
||||
import { uploadGamesBatch } from "./services/library-sync";
|
||||
import { Aria2 } from "./services/aria2";
|
||||
import { Downloader } from "@shared";
|
||||
import { IsNull, Not } from "typeorm";
|
||||
|
||||
const loadState = async (userPreferences: UserPreferences | null) => {
|
||||
import("./events");
|
||||
|
||||
Aria2.spawn();
|
||||
|
||||
if (userPreferences?.realDebridApiToken) {
|
||||
RealDebridClient.authorize(userPreferences?.realDebridApiToken);
|
||||
}
|
||||
@@ -35,11 +36,16 @@ const loadState = async (userPreferences: UserPreferences | null) => {
|
||||
},
|
||||
});
|
||||
|
||||
if (nextQueueItem?.game.status === "active") {
|
||||
DownloadManager.startDownload(nextQueueItem.game);
|
||||
} else {
|
||||
PythonInstance.spawn();
|
||||
}
|
||||
const seedList = await gameRepository.find({
|
||||
where: {
|
||||
shouldSeed: true,
|
||||
downloader: Downloader.Torrent,
|
||||
progress: 1,
|
||||
uri: Not(IsNull()),
|
||||
},
|
||||
});
|
||||
|
||||
await DownloadManager.startRPC(nextQueueItem?.game, seedList);
|
||||
|
||||
startMainLoop();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import type { HydraMigration } from "@main/knex-client";
|
||||
import type { Knex } from "knex";
|
||||
|
||||
export const AddDisableNsfwAlertColumn: HydraMigration = {
|
||||
name: "AddDisableNsfwAlertColumn",
|
||||
up: (knex: Knex) => {
|
||||
return knex.schema.alterTable("user_preferences", (table) => {
|
||||
return table.boolean("disableNsfwAlert").notNullable().defaultTo(0);
|
||||
});
|
||||
},
|
||||
|
||||
down: async (knex: Knex) => {
|
||||
return knex.schema.alterTable("user_preferences", (table) => {
|
||||
return table.dropColumn("disableNsfwAlert");
|
||||
});
|
||||
},
|
||||
};
|
||||
17
src/main/migrations/20241108200154_add_should_seed_colum.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import type { HydraMigration } from "@main/knex-client";
|
||||
import type { Knex } from "knex";
|
||||
|
||||
export const AddShouldSeedColumn: HydraMigration = {
|
||||
name: "AddShouldSeedColumn",
|
||||
up: (knex: Knex) => {
|
||||
return knex.schema.alterTable("game", (table) => {
|
||||
return table.boolean("shouldSeed").notNullable().defaultTo(true);
|
||||
});
|
||||
},
|
||||
|
||||
down: async (knex: Knex) => {
|
||||
return knex.schema.alterTable("game", (table) => {
|
||||
return table.dropColumn("shouldSeed");
|
||||
});
|
||||
},
|
||||
};
|
||||