diff --git a/src/main/services/download/download-manager.ts b/src/main/services/download/download-manager.ts index 6fc86bb6..5a18de33 100644 --- a/src/main/services/download/download-manager.ts +++ b/src/main/services/download/download-manager.ts @@ -2,7 +2,7 @@ import { Downloader } from "@shared"; import { WindowManager } from "../window-manager"; import { publishDownloadCompleteNotification } from "../notifications"; import type { Download, DownloadProgress, UserPreferences } from "@types"; -import { GofileApi, QiwiApi, DatanodesApi } from "../hosters"; +import { GofileApi, QiwiApi, DatanodesApi, MediafireApi } from "../hosters"; import { PythonRPC } from "../python-rpc"; import { LibtorrentPayload, @@ -109,7 +109,7 @@ export class DownloadManager { if (!download || !game) return; - const userPreferences = await db.get( + const userPreferences = await db.get( levelKeys.userPreferences, { valueEncoding: "json", @@ -298,6 +298,16 @@ export class DownloadManager { save_path: download.downloadPath, }; } + case Downloader.Mediafire: { + const downloadUrl = await MediafireApi.getDownloadUrl(download.uri); + + return { + action: "start", + game_id: downloadId, + url: downloadUrl, + save_path: download.downloadPath, + }; + } case Downloader.Torrent: return { action: "start", diff --git a/src/main/services/hosters/index.ts b/src/main/services/hosters/index.ts index 8cff7bd2..556897cd 100644 --- a/src/main/services/hosters/index.ts +++ b/src/main/services/hosters/index.ts @@ -1,3 +1,4 @@ export * from "./gofile"; export * from "./qiwi"; export * from "./datanodes"; +export * from "./mediafire"; diff --git a/src/main/services/hosters/mediafire.ts b/src/main/services/hosters/mediafire.ts new file mode 100644 index 00000000..41f021cb --- /dev/null +++ b/src/main/services/hosters/mediafire.ts @@ -0,0 +1,39 @@ +import axios, { AxiosResponse } from "axios"; +import { JSDOM } from "jsdom"; + +export class MediafireApi { + private static readonly session = axios.create(); + + public static async getDownloadUrl(mediafireUrl: string): Promise { + const response: AxiosResponse = 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, + } + ); + + if (response.status === 302) { + const location = response.headers["location"]; + if (!location) { + throw new Error("Missing location header in 302 redirect response"); + } + return location; + } + + 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"); + } + + return downloadButton.href; + } +} diff --git a/src/renderer/src/constants.ts b/src/renderer/src/constants.ts index d0797caf..8f20ad7a 100644 --- a/src/renderer/src/constants.ts +++ b/src/renderer/src/constants.ts @@ -9,6 +9,7 @@ export const DOWNLOADER_NAME = { [Downloader.PixelDrain]: "PixelDrain", [Downloader.Qiwi]: "Qiwi", [Downloader.Datanodes]: "Datanodes", + [Downloader.Mediafire]: "Mediafire", }; export const MAX_MINUTES_TO_SHOW_IN_PLAYTIME = 120; diff --git a/src/shared/constants.ts b/src/shared/constants.ts index f2bcc793..3f3e0a8b 100644 --- a/src/shared/constants.ts +++ b/src/shared/constants.ts @@ -5,6 +5,7 @@ export enum Downloader { PixelDrain, Qiwi, Datanodes, + Mediafire, } export enum DownloadSourceStatus { diff --git a/src/shared/index.ts b/src/shared/index.ts index cb481150..d89c7aaa 100644 --- a/src/shared/index.ts +++ b/src/shared/index.ts @@ -88,6 +88,7 @@ export const getDownloadersForUri = (uri: string) => { if (uri.startsWith("https://pixeldrain.com")) return [Downloader.PixelDrain]; if (uri.startsWith("https://qiwi.gg")) return [Downloader.Qiwi]; if (uri.startsWith("https://datanodes.to")) return [Downloader.Datanodes]; + if (uri.startsWith("https://www.mediafire.com")) return [Downloader.Mediafire]; if (realDebridHosts.some((host) => uri.startsWith(host))) return [Downloader.RealDebrid];