mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-27 04:41:03 +00:00
Merge branch 'main' into feature/torbox-integration
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Downloader } from "@shared";
|
||||
import { Downloader, DownloadError } from "@shared";
|
||||
import { WindowManager } from "../window-manager";
|
||||
import { publishDownloadCompleteNotification } from "../notifications";
|
||||
import type { Download, DownloadProgress, UserPreferences } from "@types";
|
||||
@@ -264,6 +264,8 @@ export class DownloadManager {
|
||||
const token = await GofileApi.authorize();
|
||||
const downloadLink = await GofileApi.getDownloadLink(id!);
|
||||
|
||||
await GofileApi.checkDownloadUrl(downloadLink);
|
||||
|
||||
return {
|
||||
action: "start",
|
||||
game_id: downloadId,
|
||||
@@ -320,10 +322,7 @@ export class DownloadManager {
|
||||
case Downloader.RealDebrid: {
|
||||
const downloadUrl = await RealDebridClient.getDownloadUrl(download.uri);
|
||||
|
||||
if (!downloadUrl)
|
||||
throw new Error(
|
||||
"This download is not available on Real-Debrid and polling download status from Real-Debrid is not yet available."
|
||||
);
|
||||
if (!downloadUrl) throw new Error(DownloadError.NotCachedInRealDebrid);
|
||||
|
||||
return {
|
||||
action: "start",
|
||||
|
||||
@@ -60,4 +60,12 @@ export class GofileApi {
|
||||
|
||||
throw new Error("Failed to get download link");
|
||||
}
|
||||
|
||||
public static async checkDownloadUrl(url: string) {
|
||||
return axios.head(url, {
|
||||
headers: {
|
||||
Cookie: `accountToken=${this.token}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,54 @@
|
||||
import axios, { AxiosResponse } from "axios";
|
||||
import { JSDOM } from "jsdom";
|
||||
import fetch from "node-fetch";
|
||||
|
||||
export class MediafireApi {
|
||||
private static readonly session = axios.create();
|
||||
private static readonly validMediafireIdentifierDL = /^[a-zA-Z0-9]+$/m;
|
||||
private static readonly validMediafirePreDL =
|
||||
/(?<=['"])(https?:)?(\/\/)?(www\.)?mediafire\.com\/(file|view|download)\/[^'"?]+\?dkey=[^'"]+(?=['"])/;
|
||||
private static readonly validDynamicDL =
|
||||
/(?<=['"])https?:\/\/download\d+\.mediafire\.com\/[^'"]+(?=['"])/;
|
||||
private static readonly checkHTTP = /^https?:\/\//m;
|
||||
|
||||
public static async getDownloadUrl(mediafireUrl: string): Promise<string> {
|
||||
const response: AxiosResponse<string> = await this.session.get(
|
||||
mediafireUrl,
|
||||
{
|
||||
headers: {
|
||||
"User-Agent":
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
|
||||
},
|
||||
maxRedirects: 0,
|
||||
validateStatus: (status: number) => status === 200 || status === 302,
|
||||
}
|
||||
);
|
||||
try {
|
||||
const processedUrl = this.processUrl(mediafireUrl);
|
||||
const response = await fetch(processedUrl);
|
||||
|
||||
if (response.status === 302) {
|
||||
const location = response.headers["location"];
|
||||
if (!location) {
|
||||
throw new Error("Missing location header in 302 redirect response");
|
||||
}
|
||||
return location;
|
||||
if (!response.ok) throw new Error("Failed to fetch Mediafire page");
|
||||
|
||||
const html = await response.text();
|
||||
return this.extractDirectUrl(html);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to get download URL`);
|
||||
}
|
||||
}
|
||||
|
||||
private static processUrl(url: string): string {
|
||||
let processed = url.replace("http://", "https://");
|
||||
|
||||
if (this.validMediafireIdentifierDL.test(processed)) {
|
||||
processed = `https://mediafire.com/?${processed}`;
|
||||
}
|
||||
|
||||
const dom = new JSDOM(response.data);
|
||||
const downloadButton = dom.window.document.querySelector(
|
||||
"a#downloadButton"
|
||||
) as HTMLAnchorElement;
|
||||
|
||||
if (!downloadButton?.href) {
|
||||
throw new Error("Download button URL not found in page content");
|
||||
if (!this.checkHTTP.test(processed)) {
|
||||
processed = processed.startsWith("//")
|
||||
? `https:${processed}`
|
||||
: `https://${processed}`;
|
||||
}
|
||||
|
||||
return downloadButton.href;
|
||||
return processed;
|
||||
}
|
||||
|
||||
private static extractDirectUrl(html: string): string {
|
||||
const preMatch = this.validMediafirePreDL.exec(html);
|
||||
if (preMatch?.[0]) {
|
||||
return preMatch[0];
|
||||
}
|
||||
|
||||
const dlMatch = this.validDynamicDL.exec(html);
|
||||
if (dlMatch?.[0]) {
|
||||
return dlMatch[0];
|
||||
}
|
||||
|
||||
throw new Error("No valid download links found");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,8 @@ export class WindowManager {
|
||||
this.mainWindow.removeMenu();
|
||||
|
||||
this.mainWindow.on("ready-to-show", () => {
|
||||
if (!app.isPackaged) WindowManager.mainWindow?.webContents.openDevTools();
|
||||
if (!app.isPackaged || isStaging)
|
||||
WindowManager.mainWindow?.webContents.openDevTools();
|
||||
WindowManager.mainWindow?.show();
|
||||
});
|
||||
|
||||
@@ -173,9 +174,7 @@ export class WindowManager {
|
||||
|
||||
authWindow.removeMenu();
|
||||
|
||||
if (!app.isPackaged || isStaging) {
|
||||
authWindow.webContents.openDevTools();
|
||||
}
|
||||
if (!app.isPackaged) authWindow.webContents.openDevTools();
|
||||
|
||||
authWindow.loadURL(
|
||||
`${import.meta.env.MAIN_VITE_AUTH_URL}${page}?${searchParams.toString()}`
|
||||
|
||||
Reference in New Issue
Block a user