mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-03-09 15:40:26 +00:00
feat: fixing real debrid download
This commit is contained in:
parent
fffea84ef7
commit
68b361e605
28 changed files with 241 additions and 185 deletions
|
@ -44,8 +44,6 @@ const startGameDownload = async (
|
|||
);
|
||||
|
||||
if (game) {
|
||||
console.log("game", game);
|
||||
|
||||
await gameRepository.update(
|
||||
{
|
||||
id: game.id,
|
||||
|
@ -97,8 +95,6 @@ const startGameDownload = async (
|
|||
},
|
||||
});
|
||||
|
||||
console.log(updatedGame);
|
||||
|
||||
createGame(updatedGame!);
|
||||
|
||||
await downloadQueueRepository.delete({ game: { id: updatedGame!.id } });
|
||||
|
|
|
@ -102,8 +102,6 @@ export class DownloadManager {
|
|||
const token = await GofileApi.authorize();
|
||||
const downloadLink = await GofileApi.getDownloadLink(id!);
|
||||
|
||||
console.log(downloadLink, token, "<<<");
|
||||
|
||||
GenericHTTPDownloader.startDownload(game, downloadLink, {
|
||||
Cookie: `accountToken=${token}`,
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Game } from "@main/entity";
|
|||
import { gameRepository } from "@main/repository";
|
||||
import { calculateETA } from "./helpers";
|
||||
import { DownloadProgress } from "@types";
|
||||
import { HTTPDownload } from "./http-download";
|
||||
import { HttpDownload } from "./http-download";
|
||||
|
||||
export class GenericHTTPDownloader {
|
||||
private static downloads = new Map<number, string>();
|
||||
|
@ -11,7 +11,7 @@ export class GenericHTTPDownloader {
|
|||
public static async getStatus() {
|
||||
if (this.downloadingGame) {
|
||||
const gid = this.downloads.get(this.downloadingGame.id)!;
|
||||
const status = await HTTPDownload.getStatus(gid);
|
||||
const status = HttpDownload.getStatus(gid);
|
||||
|
||||
if (status) {
|
||||
const progress =
|
||||
|
@ -60,7 +60,7 @@ export class GenericHTTPDownloader {
|
|||
const gid = this.downloads.get(this.downloadingGame!.id!);
|
||||
|
||||
if (gid) {
|
||||
await HTTPDownload.pauseDownload(gid);
|
||||
await HttpDownload.pauseDownload(gid);
|
||||
}
|
||||
|
||||
this.downloadingGame = null;
|
||||
|
@ -76,26 +76,23 @@ export class GenericHTTPDownloader {
|
|||
|
||||
if (this.downloads.has(game.id)) {
|
||||
await this.resumeDownload(game.id!);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (downloadUrl) {
|
||||
const gid = await HTTPDownload.startDownload(
|
||||
game.downloadPath!,
|
||||
downloadUrl,
|
||||
headers
|
||||
);
|
||||
const gid = await HttpDownload.startDownload(
|
||||
game.downloadPath!,
|
||||
downloadUrl,
|
||||
headers
|
||||
);
|
||||
|
||||
this.downloads.set(game.id!, gid);
|
||||
}
|
||||
this.downloads.set(game.id!, gid);
|
||||
}
|
||||
|
||||
static async cancelDownload(gameId: number) {
|
||||
const gid = this.downloads.get(gameId);
|
||||
|
||||
if (gid) {
|
||||
await HTTPDownload.cancelDownload(gid);
|
||||
await HttpDownload.cancelDownload(gid);
|
||||
this.downloads.delete(gameId);
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +101,7 @@ export class GenericHTTPDownloader {
|
|||
const gid = this.downloads.get(gameId);
|
||||
|
||||
if (gid) {
|
||||
await HTTPDownload.resumeDownload(gid);
|
||||
await HttpDownload.resumeDownload(gid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { DownloadItem } from "electron";
|
|||
import { WindowManager } from "../window-manager";
|
||||
import path from "node:path";
|
||||
|
||||
export class HTTPDownload {
|
||||
export class HttpDownload {
|
||||
private static id = 0;
|
||||
|
||||
private static downloads: Record<string, DownloadItem> = {};
|
||||
|
|
|
@ -3,7 +3,7 @@ import { RealDebridClient } from "../real-debrid";
|
|||
import { gameRepository } from "@main/repository";
|
||||
import { calculateETA } from "./helpers";
|
||||
import { DownloadProgress } from "@types";
|
||||
import { HTTPDownload } from "./http-download";
|
||||
import { HttpDownload } from "./http-download";
|
||||
|
||||
export class RealDebridDownloader {
|
||||
private static downloads = new Map<number, string>();
|
||||
|
@ -13,19 +13,23 @@ export class RealDebridDownloader {
|
|||
|
||||
private static async getRealDebridDownloadUrl() {
|
||||
if (this.realDebridTorrentId) {
|
||||
const torrentInfo = await RealDebridClient.getTorrentInfo(
|
||||
let torrentInfo = await RealDebridClient.getTorrentInfo(
|
||||
this.realDebridTorrentId
|
||||
);
|
||||
|
||||
const { status, links } = torrentInfo;
|
||||
|
||||
if (status === "waiting_files_selection") {
|
||||
if (torrentInfo.status === "waiting_files_selection") {
|
||||
await RealDebridClient.selectAllFiles(this.realDebridTorrentId);
|
||||
return null;
|
||||
|
||||
torrentInfo = await RealDebridClient.getTorrentInfo(
|
||||
this.realDebridTorrentId
|
||||
);
|
||||
}
|
||||
|
||||
const { links, status } = torrentInfo;
|
||||
|
||||
if (status === "downloaded") {
|
||||
const [link] = links;
|
||||
|
||||
const { download } = await RealDebridClient.unrestrictLink(link);
|
||||
return decodeURIComponent(download);
|
||||
}
|
||||
|
@ -38,8 +42,6 @@ export class RealDebridDownloader {
|
|||
this.downloadingGame?.uri
|
||||
);
|
||||
|
||||
console.log("download>>", download);
|
||||
|
||||
return decodeURIComponent(download);
|
||||
}
|
||||
|
||||
|
@ -49,7 +51,7 @@ export class RealDebridDownloader {
|
|||
public static async getStatus() {
|
||||
if (this.downloadingGame) {
|
||||
const gid = this.downloads.get(this.downloadingGame.id)!;
|
||||
const status = await HTTPDownload.getStatus(gid);
|
||||
const status = HttpDownload.getStatus(gid);
|
||||
|
||||
if (status) {
|
||||
const progress =
|
||||
|
@ -91,33 +93,6 @@ export class RealDebridDownloader {
|
|||
}
|
||||
}
|
||||
|
||||
if (this.realDebridTorrentId && this.downloadingGame) {
|
||||
const torrentInfo = await RealDebridClient.getTorrentInfo(
|
||||
this.realDebridTorrentId
|
||||
);
|
||||
|
||||
const { status } = torrentInfo;
|
||||
|
||||
if (status === "downloaded") {
|
||||
this.startDownload(this.downloadingGame);
|
||||
}
|
||||
|
||||
const progress = torrentInfo.progress / 100;
|
||||
const totalDownloaded = progress * torrentInfo.bytes;
|
||||
|
||||
return {
|
||||
numPeers: 0,
|
||||
numSeeds: torrentInfo.seeders,
|
||||
downloadSpeed: torrentInfo.speed,
|
||||
timeRemaining: calculateETA(
|
||||
torrentInfo.bytes,
|
||||
totalDownloaded,
|
||||
torrentInfo.speed
|
||||
),
|
||||
isDownloadingMetadata: status === "magnet_conversion",
|
||||
} as DownloadProgress;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -125,7 +100,7 @@ export class RealDebridDownloader {
|
|||
if (this.downloadingGame) {
|
||||
const gid = this.downloads.get(this.downloadingGame.id);
|
||||
if (gid) {
|
||||
await HTTPDownload.pauseDownload(gid);
|
||||
await HttpDownload.pauseDownload(gid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,18 +121,19 @@ export class RealDebridDownloader {
|
|||
);
|
||||
}
|
||||
|
||||
this.downloadingGame = game;
|
||||
|
||||
const downloadUrl = await this.getRealDebridDownloadUrl();
|
||||
|
||||
if (downloadUrl) {
|
||||
this.realDebridTorrentId = null;
|
||||
|
||||
const gid = await HTTPDownload.startDownload(
|
||||
const gid = await HttpDownload.startDownload(
|
||||
game.downloadPath!,
|
||||
downloadUrl
|
||||
);
|
||||
|
||||
this.downloads.set(game.id!, gid);
|
||||
this.downloadingGame = game;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,7 +141,7 @@ export class RealDebridDownloader {
|
|||
const gid = this.downloads.get(gameId);
|
||||
|
||||
if (gid) {
|
||||
await HTTPDownload.cancelDownload(gid);
|
||||
await HttpDownload.cancelDownload(gid);
|
||||
this.downloads.delete(gameId);
|
||||
}
|
||||
|
||||
|
@ -177,7 +153,7 @@ export class RealDebridDownloader {
|
|||
const gid = this.downloads.get(gameId);
|
||||
|
||||
if (gid) {
|
||||
await HTTPDownload.resumeDownload(gid);
|
||||
await HttpDownload.resumeDownload(gid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ export class RealDebridClient {
|
|||
static async selectAllFiles(id: string) {
|
||||
const searchParams = new URLSearchParams({ files: "all" });
|
||||
|
||||
await this.instance.post(
|
||||
return this.instance.post(
|
||||
`/torrents/selectFiles/${id}`,
|
||||
searchParams.toString()
|
||||
);
|
||||
|
|
|
@ -26,7 +26,7 @@ globalStyle("html, body, #root, main", {
|
|||
globalStyle("body", {
|
||||
overflow: "hidden",
|
||||
userSelect: "none",
|
||||
fontFamily: "'Fira Mono', monospace",
|
||||
fontFamily: "Noto Sans, sans-serif",
|
||||
fontSize: vars.size.body,
|
||||
background: vars.color.background,
|
||||
color: vars.color.body,
|
||||
|
|
|
@ -45,7 +45,6 @@ export const description = style({
|
|||
maxWidth: "700px",
|
||||
color: vars.color.muted,
|
||||
textAlign: "left",
|
||||
fontFamily: "'Fira Sans', sans-serif",
|
||||
lineHeight: "20px",
|
||||
marginTop: `${SPACING_UNIT * 2}px`,
|
||||
});
|
||||
|
|
|
@ -24,6 +24,7 @@ export const modal = recipe({
|
|||
animation: `${scaleFadeIn} 0.2s cubic-bezier(0.33, 1, 0.68, 1) 0s 1 normal none running`,
|
||||
backgroundColor: vars.color.background,
|
||||
borderRadius: "4px",
|
||||
minWidth: "400px",
|
||||
maxWidth: "600px",
|
||||
color: vars.color.body,
|
||||
maxHeight: "100%",
|
||||
|
|
|
@ -8,12 +8,10 @@ import { HashRouter, Route, Routes } from "react-router-dom";
|
|||
|
||||
import * as Sentry from "@sentry/electron/renderer";
|
||||
|
||||
import "@fontsource/fira-mono/400.css";
|
||||
import "@fontsource/fira-mono/500.css";
|
||||
import "@fontsource/fira-mono/700.css";
|
||||
import "@fontsource/fira-sans/400.css";
|
||||
import "@fontsource/fira-sans/500.css";
|
||||
import "@fontsource/fira-sans/700.css";
|
||||
import "@fontsource/noto-sans/400.css";
|
||||
import "@fontsource/noto-sans/500.css";
|
||||
import "@fontsource/noto-sans/700.css";
|
||||
|
||||
import "react-loading-skeleton/dist/skeleton.css";
|
||||
|
||||
import { App } from "./app";
|
||||
|
|
|
@ -132,9 +132,7 @@ export function Downloads() {
|
|||
<ArrowDownIcon size={24} />
|
||||
</div>
|
||||
<h2>{t("no_downloads_title")}</h2>
|
||||
<p style={{ fontFamily: "Fira Sans" }}>
|
||||
{t("no_downloads_description")}
|
||||
</p>
|
||||
<p>{t("no_downloads_description")}</p>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
|
|
@ -19,7 +19,10 @@ export function DescriptionHeader() {
|
|||
date: shopDetails?.release_date.date,
|
||||
})}
|
||||
</p>
|
||||
<p>{t("publisher", { publisher: shopDetails.publishers[0] })}</p>
|
||||
|
||||
{Array.isArray(shopDetails.publishers) && (
|
||||
<p>{t("publisher", { publisher: shopDetails.publishers[0] })}</p>
|
||||
)}
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -101,7 +101,6 @@ export const descriptionContent = style({
|
|||
export const description = style({
|
||||
userSelect: "text",
|
||||
lineHeight: "22px",
|
||||
fontFamily: "'Fira Sans', sans-serif",
|
||||
fontSize: "16px",
|
||||
padding: `${SPACING_UNIT * 3}px ${SPACING_UNIT * 2}px`,
|
||||
"@media": {
|
||||
|
|
|
@ -9,6 +9,7 @@ export const panel = recipe({
|
|||
height: "72px",
|
||||
minHeight: "72px",
|
||||
padding: `${SPACING_UNIT * 2}px ${SPACING_UNIT * 3}px`,
|
||||
backgroundColor: vars.color.darkBackground,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
|
|
|
@ -60,14 +60,22 @@ export function DownloadSettingsModal({
|
|||
.then((defaultDownloadsPath) => setSelectedPath(defaultDownloadsPath));
|
||||
}
|
||||
|
||||
if (
|
||||
userPreferences?.realDebridApiToken &&
|
||||
downloaders.includes(Downloader.RealDebrid)
|
||||
) {
|
||||
setSelectedDownloader(Downloader.RealDebrid);
|
||||
} else {
|
||||
setSelectedDownloader(downloaders[0]);
|
||||
}
|
||||
const filteredDownloaders = downloaders.filter((downloader) => {
|
||||
if (downloader === Downloader.RealDebrid)
|
||||
return userPreferences?.realDebridApiToken;
|
||||
return true;
|
||||
});
|
||||
|
||||
/* Gives preference to Real Debrid */
|
||||
const selectedDownloader = filteredDownloaders.includes(
|
||||
Downloader.RealDebrid
|
||||
)
|
||||
? Downloader.RealDebrid
|
||||
: filteredDownloaders[0];
|
||||
|
||||
setSelectedDownloader(
|
||||
selectedDownloader === undefined ? null : selectedDownloader
|
||||
);
|
||||
}, [
|
||||
userPreferences?.downloadsPath,
|
||||
downloaders,
|
||||
|
|
|
@ -15,7 +15,6 @@ export const gameOptionHeader = style({
|
|||
});
|
||||
|
||||
export const gameOptionHeaderDescription = style({
|
||||
fontFamily: "'Fira Sans', sans-serif",
|
||||
fontWeight: "400",
|
||||
});
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ export const requirementButton = style({
|
|||
export const requirementsDetails = style({
|
||||
padding: `${SPACING_UNIT * 2}px`,
|
||||
lineHeight: "22px",
|
||||
fontFamily: "'Fira Sans', sans-serif",
|
||||
fontSize: "16px",
|
||||
});
|
||||
|
||||
|
|
|
@ -82,9 +82,7 @@ export function SettingsDownloadSources() {
|
|||
onAddDownloadSource={handleAddDownloadSource}
|
||||
/>
|
||||
|
||||
<p style={{ fontFamily: '"Fira Sans"' }}>
|
||||
{t("download_sources_description")}
|
||||
</p>
|
||||
<p>{t("download_sources_description")}</p>
|
||||
|
||||
<div className={styles.downloadSourcesHeader}>
|
||||
<Button
|
||||
|
|
|
@ -9,6 +9,5 @@ export const form = style({
|
|||
});
|
||||
|
||||
export const description = style({
|
||||
fontFamily: "'Fira Sans', sans-serif",
|
||||
marginBottom: `${SPACING_UNIT * 2}px`,
|
||||
});
|
||||
|
|
|
@ -25,9 +25,7 @@ export const UserBlockModal = ({
|
|||
onClose={onClose}
|
||||
>
|
||||
<div className={styles.signOutModalContent}>
|
||||
<p style={{ fontFamily: "Fira Sans" }}>
|
||||
{t("user_block_modal_text", { displayName })}
|
||||
</p>
|
||||
<p>{t("user_block_modal_text", { displayName })}</p>
|
||||
<div className={styles.signOutModalButtonsContainer}>
|
||||
<Button onClick={onConfirm} theme="danger">
|
||||
{t("block_user")}
|
||||
|
|
|
@ -371,11 +371,7 @@ export function UserContent({
|
|||
<TelescopeIcon size={24} />
|
||||
</div>
|
||||
<h2>{t("no_recent_activity_title")}</h2>
|
||||
{isMe && (
|
||||
<p style={{ fontFamily: "Fira Sans" }}>
|
||||
{t("no_recent_activity_description")}
|
||||
</p>
|
||||
)}
|
||||
{isMe && <p>{t("no_recent_activity_description")}</p>}
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
|
|
|
@ -23,7 +23,7 @@ export const UserSignOutModal = ({
|
|||
onClose={onClose}
|
||||
>
|
||||
<div className={styles.signOutModalContent}>
|
||||
<p style={{ fontFamily: "Fira Sans" }}>{t("sign_out_modal_text")}</p>
|
||||
<p>{t("sign_out_modal_text")}</p>
|
||||
<div className={styles.signOutModalButtonsContainer}>
|
||||
<Button onClick={onConfirm} theme="danger">
|
||||
{t("sign_out")}
|
||||
|
|
|
@ -53,6 +53,8 @@ export const removeSpecialEditionFromName = (name: string) =>
|
|||
export const removeDuplicateSpaces = (name: string) =>
|
||||
name.replace(/\s{2,}/g, " ");
|
||||
|
||||
export const replaceDotsWithSpace = (name: string) => name.replace(/\./g, " ");
|
||||
|
||||
export const replaceUnderscoreWithSpace = (name: string) =>
|
||||
name.replace(/_/g, " ");
|
||||
|
||||
|
@ -60,6 +62,7 @@ export const formatName = pipe<string>(
|
|||
removeReleaseYearFromName,
|
||||
removeSpecialEditionFromName,
|
||||
replaceUnderscoreWithSpace,
|
||||
replaceDotsWithSpace,
|
||||
(str) => str.replace(/DIRECTOR'S CUT/g, ""),
|
||||
removeSymbolsFromName,
|
||||
removeDuplicateSpaces,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue