mirror of
https://github.com/lifegpc/eh-downloader.git
synced 2026-06-06 05:38:44 +08:00
Update
This commit is contained in:
@@ -6,6 +6,7 @@ import { DiscriminatedUnion } from "../../utils.ts";
|
||||
type EventMap = {
|
||||
close: Record<PropertyKey, never>;
|
||||
new_download_task: { gid: number; token: string };
|
||||
new_export_zip_task: { gid: number; output?: string };
|
||||
};
|
||||
|
||||
type EventData = DiscriminatedUnion<"type", EventMap>;
|
||||
@@ -37,6 +38,8 @@ export const handler: Handlers<Task[]> = {
|
||||
socket.close();
|
||||
} else if (d.type == "new_download_task") {
|
||||
t.add_download_task(d.gid, d.token);
|
||||
} else if (d.type == "new_export_zip_task") {
|
||||
t.add_export_zip_task(d.gid, d.output);
|
||||
}
|
||||
} catch (_) {
|
||||
null;
|
||||
|
||||
12
task.ts
12
task.ts
@@ -24,9 +24,15 @@ export type TaskExportZipProgress = {
|
||||
total_page: number;
|
||||
};
|
||||
|
||||
export type TaskProgressType = {
|
||||
[TaskType.Download]: TaskDownloadProgess;
|
||||
[TaskType.ExportZip]: TaskExportZipProgress;
|
||||
type TaskId<T extends Record<PropertyKey, unknown>> = {
|
||||
[P in keyof T]: ({
|
||||
task_id: number;
|
||||
} & T[P]) extends infer U ? { [Q in keyof U]: U[Q] } : never;
|
||||
};
|
||||
|
||||
export type TaskProgressType = TaskId<{
|
||||
[TaskType.Download]: TaskDownloadProgess;
|
||||
[TaskType.ExportZip]: TaskExportZipProgress;
|
||||
}>;
|
||||
|
||||
export type TaskProgress = DiscriminatedUnion<"type", TaskProgressType>;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Config } from "./config.ts";
|
||||
import { EhDb } from "./db.ts";
|
||||
import { check_running } from "./pid_check.ts";
|
||||
import { add_exit_handler } from "./signal_handler.ts";
|
||||
import { Task, TaskProgress, TaskType } from "./task.ts";
|
||||
import { Task, TaskProgress, TaskProgressType, TaskType } from "./task.ts";
|
||||
import { download_task } from "./tasks/download.ts";
|
||||
import {
|
||||
DEFAULT_EXPORT_ZIP_CONFIG,
|
||||
@@ -157,6 +157,15 @@ export class TaskManager extends EventTarget {
|
||||
dispatchEvent<T extends keyof EventMap>(type: T, detail: EventMap[T]) {
|
||||
return super.dispatchEvent(new CustomEvent(type, { detail }));
|
||||
}
|
||||
dispatchTaskProgressEvent<T extends keyof TaskProgressType>(
|
||||
type: T,
|
||||
detail: TaskProgressType[T],
|
||||
) {
|
||||
return this.dispatchEvent(
|
||||
"task_progress",
|
||||
<TaskProgress> <unknown> { type, ...detail },
|
||||
);
|
||||
}
|
||||
force_abort(reason?: unknown) {
|
||||
this.#force_abort.abort(reason);
|
||||
}
|
||||
@@ -208,6 +217,7 @@ export class TaskManager extends EventTarget {
|
||||
}
|
||||
run_task(task: Task) {
|
||||
this.#check_closed();
|
||||
this.dispatchEvent("task_started", task);
|
||||
if (task.type == TaskType.Download) {
|
||||
this.running_tasks.set(
|
||||
task.id,
|
||||
@@ -218,6 +228,7 @@ export class TaskManager extends EventTarget {
|
||||
this.cfg,
|
||||
this.#abort.signal,
|
||||
this.#force_abort.signal,
|
||||
this,
|
||||
),
|
||||
);
|
||||
} else if (task.type == TaskType.ExportZip) {
|
||||
@@ -232,10 +243,10 @@ export class TaskManager extends EventTarget {
|
||||
this.cfg,
|
||||
this.#abort.signal,
|
||||
cfg,
|
||||
this,
|
||||
),
|
||||
);
|
||||
}
|
||||
this.dispatchEvent("task_started", task);
|
||||
}
|
||||
async waiting_unfinished_task() {
|
||||
while (1) {
|
||||
|
||||
@@ -2,7 +2,8 @@ import { assert } from "std/testing/asserts.ts";
|
||||
import { Client } from "../client.ts";
|
||||
import { Config } from "../config.ts";
|
||||
import { EhDb } from "../db.ts";
|
||||
import { Task } from "../task.ts";
|
||||
import { Task, TaskDownloadProgess, TaskType } from "../task.ts";
|
||||
import { TaskManager } from "../task_manager.ts";
|
||||
import {
|
||||
asyncFilter,
|
||||
promiseState,
|
||||
@@ -19,11 +20,23 @@ class DownloadManager {
|
||||
#max_download_count;
|
||||
#running_tasks: Promise<unknown>[];
|
||||
#has_failed_task = false;
|
||||
constructor(cfg: Config, abort: AbortSignal, force_abort: AbortSignal) {
|
||||
#progress: TaskDownloadProgess;
|
||||
#task: Task;
|
||||
#manager: TaskManager;
|
||||
constructor(
|
||||
cfg: Config,
|
||||
abort: AbortSignal,
|
||||
force_abort: AbortSignal,
|
||||
task: Task,
|
||||
manager: TaskManager,
|
||||
) {
|
||||
this.#max_download_count = cfg.max_download_img_count;
|
||||
this.#running_tasks = [];
|
||||
this.#abort = abort;
|
||||
this.#force_abort = force_abort;
|
||||
this.#progress = { total_page: 0, downloaded_page: 0 };
|
||||
this.#task = task;
|
||||
this.#manager = manager;
|
||||
}
|
||||
async #check_tasks() {
|
||||
this.#running_tasks = await asyncFilter(
|
||||
@@ -33,11 +46,21 @@ class DownloadManager {
|
||||
if (s.status === PromiseStatus.Rejected) {
|
||||
if (!this.#force_abort.aborted) console.log(s.reason);
|
||||
this.#has_failed_task = true;
|
||||
} else if (s.status === PromiseStatus.Fulfilled) {
|
||||
this.#progress.downloaded_page += 1;
|
||||
this.#sendEvent();
|
||||
}
|
||||
return s.status === PromiseStatus.Pending;
|
||||
},
|
||||
);
|
||||
}
|
||||
#sendEvent() {
|
||||
return this.#manager.dispatchTaskProgressEvent(TaskType.Download, {
|
||||
task_id: this.#task.id,
|
||||
downloaded_page: this.#progress.downloaded_page,
|
||||
total_page: this.#progress.total_page,
|
||||
});
|
||||
}
|
||||
async add_new_task(f: () => Promise<unknown>) {
|
||||
while (1) {
|
||||
if (this.#abort.aborted) break;
|
||||
@@ -59,6 +82,10 @@ class DownloadManager {
|
||||
await sleep(10);
|
||||
}
|
||||
}
|
||||
set_total_page(page: number) {
|
||||
this.#progress.total_page = page;
|
||||
this.#sendEvent();
|
||||
}
|
||||
}
|
||||
|
||||
export async function download_task(
|
||||
@@ -68,6 +95,7 @@ export async function download_task(
|
||||
cfg: Config,
|
||||
abort: AbortSignal,
|
||||
force_abort: AbortSignal,
|
||||
manager: TaskManager,
|
||||
) {
|
||||
console.log("Started to download gallery", task.gid);
|
||||
const gdatas = await client.fetchGalleryMetadataByAPI([
|
||||
@@ -82,9 +110,10 @@ export async function download_task(
|
||||
await db.add_gtag(task.gid, new Set(gdata.tags));
|
||||
const base_path = join(cfg.base, task.gid.toString());
|
||||
await sure_dir(base_path);
|
||||
const m = new DownloadManager(cfg, abort, force_abort);
|
||||
const m = new DownloadManager(cfg, abort, force_abort, task, manager);
|
||||
if (cfg.mpv) {
|
||||
const mpv = await client.fetchMPVPage(task.gid, task.token);
|
||||
m.set_total_page(mpv.pagecount);
|
||||
for (const i of mpv.imagelist) {
|
||||
if (abort.aborted) break;
|
||||
await m.add_new_task(async () => {
|
||||
|
||||
@@ -3,7 +3,8 @@ import { Uint8ArrayReader, ZipWriter } from "zipjs/index.js";
|
||||
import { EhDb } from "../db.ts";
|
||||
import { addZero, asyncForEach, filterFilename } from "../utils.ts";
|
||||
import { Config } from "../config.ts";
|
||||
import { Task } from "../task.ts";
|
||||
import { Task, TaskExportZipProgress, TaskType } from "../task.ts";
|
||||
import { TaskManager } from "../task_manager.ts";
|
||||
|
||||
export type ExportZipConfig = {
|
||||
output?: string;
|
||||
@@ -17,10 +18,23 @@ export async function export_zip(
|
||||
cfg: Config,
|
||||
signal: AbortSignal,
|
||||
ecfg: ExportZipConfig,
|
||||
manager: TaskManager,
|
||||
) {
|
||||
const gid = task.gid;
|
||||
const g = db.get_gmeta_by_gid(gid);
|
||||
if (!g) throw Error("Gallery not found in database.");
|
||||
const progress: TaskExportZipProgress = {
|
||||
total_page: g.filecount,
|
||||
added_page: 0,
|
||||
};
|
||||
const sendEvent = () => {
|
||||
manager.dispatchTaskProgressEvent(TaskType.ExportZip, {
|
||||
task_id: task.id,
|
||||
added_page: progress.added_page,
|
||||
total_page: progress.total_page,
|
||||
});
|
||||
};
|
||||
sendEvent();
|
||||
const output = ecfg.output === undefined
|
||||
? join(cfg.base, filterFilename(g.title + ".zip"))
|
||||
: ecfg.output;
|
||||
@@ -47,6 +61,8 @@ export async function export_zip(
|
||||
{ signal },
|
||||
);
|
||||
}
|
||||
progress.added_page += 1;
|
||||
sendEvent();
|
||||
},
|
||||
);
|
||||
await z.close();
|
||||
|
||||
Reference in New Issue
Block a user