refactor: improve code formatting and logging consistency in download manager and buzzheavier services

This commit is contained in:
Moyasee
2025-12-26 23:38:01 +02:00
parent 0b4d31e482
commit 263d0be4e4
2 changed files with 92 additions and 34 deletions

View File

@@ -29,20 +29,23 @@ import { BuzzheavierApi, FuckingFastApi } from "@main/services/hosters";
export class DownloadManager { export class DownloadManager {
private static downloadingGameId: string | null = null; private static downloadingGameId: string | null = null;
private static extractFilename(url: string, originalUrl?: string): string | undefined { private static extractFilename(
if (originalUrl?.includes('#')) { url: string,
const hashPart = originalUrl.split('#')[1]; originalUrl?: string
if (hashPart && !hashPart.startsWith('http')) return hashPart; ): string | undefined {
if (originalUrl?.includes("#")) {
const hashPart = originalUrl.split("#")[1];
if (hashPart && !hashPart.startsWith("http")) return hashPart;
} }
if (url.includes('#')) { if (url.includes("#")) {
const hashPart = url.split('#')[1]; const hashPart = url.split("#")[1];
if (hashPart && !hashPart.startsWith('http')) return hashPart; if (hashPart && !hashPart.startsWith("http")) return hashPart;
} }
try { try {
const urlObj = new URL(url); const urlObj = new URL(url);
const filename = urlObj.pathname.split('/').pop(); const filename = urlObj.pathname.split("/").pop();
if (filename?.length) return filename; if (filename?.length) return filename;
} catch { } catch {
// Invalid URL // Invalid URL
@@ -52,13 +55,20 @@ export class DownloadManager {
} }
private static sanitizeFilename(filename: string): string { private static sanitizeFilename(filename: string): string {
return filename.replace(/[<>:"/\\|?*]/g, '_'); return filename.replace(/[<>:"/\\|?*]/g, "_");
} }
private static createDownloadPayload(directUrl: string, originalUrl: string, downloadId: string, savePath: string) { private static createDownloadPayload(
directUrl: string,
originalUrl: string,
downloadId: string,
savePath: string
) {
const filename = this.extractFilename(directUrl, originalUrl); const filename = this.extractFilename(directUrl, originalUrl);
const sanitizedFilename = filename ? this.sanitizeFilename(filename) : undefined; const sanitizedFilename = filename
? this.sanitizeFilename(filename)
: undefined;
if (sanitizedFilename) { if (sanitizedFilename) {
logger.log(`[DownloadManager] Using filename: ${sanitizedFilename}`); logger.log(`[DownloadManager] Using filename: ${sanitizedFilename}`);
} }
@@ -98,7 +108,9 @@ export class DownloadManager {
} }
private static async getDownloadStatus() { private static async getDownloadStatus() {
const response = await PythonRPC.rpc.get<LibtorrentPayload | null>("/status"); const response = await PythonRPC.rpc.get<LibtorrentPayload | null>(
"/status"
);
if (response.data === null || !this.downloadingGameId) return null; if (response.data === null || !this.downloadingGameId) return null;
const downloadId = this.downloadingGameId; const downloadId = this.downloadingGameId;
@@ -114,7 +126,8 @@ export class DownloadManager {
status, status,
} = response.data; } = response.data;
const isDownloadingMetadata = status === LibtorrentStatus.DownloadingMetadata; const isDownloadingMetadata =
status === LibtorrentStatus.DownloadingMetadata;
const isCheckingFiles = status === LibtorrentStatus.CheckingFiles; const isCheckingFiles = status === LibtorrentStatus.CheckingFiles;
const download = await downloadsSublevel.get(downloadId); const download = await downloadsSublevel.get(downloadId);
@@ -179,7 +192,10 @@ export class DownloadManager {
if (progress === 1 && download) { if (progress === 1 && download) {
publishDownloadCompleteNotification(game); publishDownloadCompleteNotification(game);
if (userPreferences?.seedAfterDownloadComplete && download.downloader === Downloader.Torrent) { if (
userPreferences?.seedAfterDownloadComplete &&
download.downloader === Downloader.Torrent
) {
await downloadsSublevel.put(gameId, { await downloadsSublevel.put(gameId, {
...download, ...download,
status: "seeding", status: "seeding",
@@ -200,13 +216,22 @@ export class DownloadManager {
} }
if (shouldExtract) { if (shouldExtract) {
const gameFilesManager = new GameFilesManager(game.shop, game.objectId); const gameFilesManager = new GameFilesManager(
game.shop,
game.objectId
);
if (FILE_EXTENSIONS_TO_EXTRACT.some((ext) => download.folderName?.endsWith(ext))) { if (
FILE_EXTENSIONS_TO_EXTRACT.some((ext) =>
download.folderName?.endsWith(ext)
)
) {
gameFilesManager.extractDownloadedFile(); gameFilesManager.extractDownloadedFile();
} else { } else {
gameFilesManager gameFilesManager
.extractFilesInDirectory(path.join(download.downloadPath, download.folderName!)) .extractFilesInDirectory(
path.join(download.downloadPath, download.folderName!)
)
.then(() => gameFilesManager.setExtractionComplete()); .then(() => gameFilesManager.setExtractionComplete());
} }
} }
@@ -214,11 +239,13 @@ export class DownloadManager {
const downloads = await downloadsSublevel const downloads = await downloadsSublevel
.values() .values()
.all() .all()
.then((games) => sortBy( .then((games) =>
games.filter((game) => game.status === "paused" && game.queued), sortBy(
"timestamp", games.filter((game) => game.status === "paused" && game.queued),
"DESC" "timestamp",
)); "DESC"
)
);
const [nextItemOnQueue] = downloads; const [nextItemOnQueue] = downloads;
@@ -245,7 +272,9 @@ export class DownloadManager {
if (!download) return; if (!download) return;
const totalSize = await getDirSize(path.join(download.downloadPath, status.folderName)); const totalSize = await getDirSize(
path.join(download.downloadPath, status.folderName)
);
if (totalSize < status.fileSize) { if (totalSize < status.fileSize) {
await this.cancelDownload(status.gameId); await this.cancelDownload(status.gameId);
@@ -266,7 +295,10 @@ export class DownloadManager {
static async pauseDownload(downloadKey = this.downloadingGameId) { static async pauseDownload(downloadKey = this.downloadingGameId) {
await PythonRPC.rpc await PythonRPC.rpc
.post("/action", { action: "pause", game_id: downloadKey } as PauseDownloadPayload) .post("/action", {
action: "pause",
game_id: downloadKey,
} as PauseDownloadPayload)
.catch(() => {}); .catch(() => {});
if (downloadKey === this.downloadingGameId) { if (downloadKey === this.downloadingGameId) {
@@ -357,24 +389,44 @@ export class DownloadManager {
}; };
} }
case Downloader.Buzzheavier: { case Downloader.Buzzheavier: {
logger.log(`[DownloadManager] Processing Buzzheavier download for URI: ${download.uri}`); logger.log(
`[DownloadManager] Processing Buzzheavier download for URI: ${download.uri}`
);
try { try {
const directUrl = await BuzzheavierApi.getDirectLink(download.uri); const directUrl = await BuzzheavierApi.getDirectLink(download.uri);
logger.log(`[DownloadManager] Buzzheavier direct URL obtained`); logger.log(`[DownloadManager] Buzzheavier direct URL obtained`);
return this.createDownloadPayload(directUrl, download.uri, downloadId, download.downloadPath); return this.createDownloadPayload(
directUrl,
download.uri,
downloadId,
download.downloadPath
);
} catch (error) { } catch (error) {
logger.error(`[DownloadManager] Error processing Buzzheavier download:`, error); logger.error(
`[DownloadManager] Error processing Buzzheavier download:`,
error
);
throw error; throw error;
} }
} }
case Downloader.FuckingFast: { case Downloader.FuckingFast: {
logger.log(`[DownloadManager] Processing FuckingFast download for URI: ${download.uri}`); logger.log(
`[DownloadManager] Processing FuckingFast download for URI: ${download.uri}`
);
try { try {
const directUrl = await FuckingFastApi.getDirectLink(download.uri); const directUrl = await FuckingFastApi.getDirectLink(download.uri);
logger.log(`[DownloadManager] FuckingFast direct URL obtained`); logger.log(`[DownloadManager] FuckingFast direct URL obtained`);
return this.createDownloadPayload(directUrl, download.uri, downloadId, download.downloadPath); return this.createDownloadPayload(
directUrl,
download.uri,
downloadId,
download.downloadPath
);
} catch (error) { } catch (error) {
logger.error(`[DownloadManager] Error processing FuckingFast download:`, error); logger.error(
`[DownloadManager] Error processing FuckingFast download:`,
error
);
throw error; throw error;
} }
} }
@@ -419,7 +471,9 @@ export class DownloadManager {
}; };
} }
case Downloader.Hydra: { case Downloader.Hydra: {
const downloadUrl = await HydraDebridClient.getDownloadUrl(download.uri); const downloadUrl = await HydraDebridClient.getDownloadUrl(
download.uri
);
if (!downloadUrl) throw new Error(DownloadError.NotCachedOnHydra); if (!downloadUrl) throw new Error(DownloadError.NotCachedOnHydra);
return { return {

View File

@@ -21,7 +21,9 @@ export class BuzzheavierApi {
private static async getBuzzheavierDirectLink(url: string): Promise<string> { private static async getBuzzheavierDirectLink(url: string): Promise<string> {
try { try {
const baseUrl = url.split("#")[0]; const baseUrl = url.split("#")[0];
logger.log(`[Buzzheavier] Starting download link extraction for: ${baseUrl}`); logger.log(
`[Buzzheavier] Starting download link extraction for: ${baseUrl}`
);
await axios.get(baseUrl, { await axios.get(baseUrl, {
headers: { "User-Agent": HOSTER_USER_AGENT }, headers: { "User-Agent": HOSTER_USER_AGENT },
@@ -46,7 +48,9 @@ export class BuzzheavierApi {
const hxRedirect = headResponse.headers["hx-redirect"]; const hxRedirect = headResponse.headers["hx-redirect"];
logger.log(`[Buzzheavier] Received hx-redirect header: ${hxRedirect}`); logger.log(`[Buzzheavier] Received hx-redirect header: ${hxRedirect}`);
if (!hxRedirect) { if (!hxRedirect) {
logger.error(`[Buzzheavier] No hx-redirect header found. Status: ${headResponse.status}`); logger.error(
`[Buzzheavier] No hx-redirect header found. Status: ${headResponse.status}`
);
throw new Error( throw new Error(
"Could not extract download link. File may be deleted or is a directory." "Could not extract download link. File may be deleted or is a directory."
); );