First upload version 0.0.1

This commit is contained in:
Neyra
2026-02-05 15:27:49 +08:00
commit 8e9b7201ed
4182 changed files with 593136 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
import { SaveProgressInfo } from "../../types.js";
export type ProgramSlice = {
start: number;
end: number;
};
export type DownloadSlice = (startChunk: number, endChunk: number) => Promise<void>;
export default abstract class BaseDownloadProgram {
protected savedProgress: SaveProgressInfo;
protected readonly _downloadSlice: DownloadSlice;
protected _aborted: boolean;
protected constructor(_savedProgress: SaveProgressInfo, _downloadSlice: DownloadSlice);
download(): Promise<void>;
protected abstract _createOneSlice(): ProgramSlice | null;
abort(): void;
}

View File

@@ -0,0 +1,38 @@
export default class BaseDownloadProgram {
savedProgress;
_downloadSlice;
_aborted = false;
constructor(_savedProgress, _downloadSlice) {
this._downloadSlice = _downloadSlice;
this.savedProgress = _savedProgress;
}
async download() {
if (this.savedProgress.parallelStreams === 1) {
return await this._downloadSlice(0, this.savedProgress.chunks.length);
}
const activeDownloads = [];
// eslint-disable-next-line no-constant-condition
while (true) {
while (activeDownloads.length >= this.savedProgress.parallelStreams) {
if (this._aborted)
return;
await Promise.race(activeDownloads);
}
const slice = this._createOneSlice();
if (slice == null)
break;
if (this._aborted)
return;
const promise = this._downloadSlice(slice.start, slice.end);
activeDownloads.push(promise);
promise.then(() => {
activeDownloads.splice(activeDownloads.indexOf(promise), 1);
});
}
await Promise.all(activeDownloads);
}
abort() {
this._aborted = true;
}
}
//# sourceMappingURL=base-download-program.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"base-download-program.js","sourceRoot":"","sources":["../../../../../src/download/download-engine/download-file/download-programs/base-download-program.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,OAAO,OAAgB,mBAAmB;IACnC,aAAa,CAAmB;IACvB,cAAc,CAAgB;IACvC,QAAQ,GAAG,KAAK,CAAC;IAE3B,YAAsB,cAAgC,EAAE,cAA6B;QACjF,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,aAAa,GAAG,cAAc,CAAC;IACxC,CAAC;IAEM,KAAK,CAAC,QAAQ;QACjB,IAAI,IAAI,CAAC,aAAa,CAAC,eAAe,KAAK,CAAC,EAAE,CAAC;YAC3C,OAAO,MAAM,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC1E,CAAC;QAED,MAAM,eAAe,GAAmB,EAAE,CAAC;QAE3C,iDAAiD;QACjD,OAAO,IAAI,EAAE,CAAC;YACV,OAAO,eAAe,CAAC,MAAM,IAAI,IAAI,CAAC,aAAa,CAAC,eAAe,EAAE,CAAC;gBAClE,IAAI,IAAI,CAAC,QAAQ;oBAAE,OAAO;gBAC1B,MAAM,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YACxC,CAAC;YAED,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YACrC,IAAI,KAAK,IAAI,IAAI;gBAAE,MAAM;YAEzB,IAAI,IAAI,CAAC,QAAQ;gBAAE,OAAO;YAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;YAC5D,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE;gBACd,eAAe,CAAC,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;YAChE,CAAC,CAAC,CAAC;QACP,CAAC;QAED,MAAM,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACvC,CAAC;IAIM,KAAK;QACR,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IACzB,CAAC;CACJ"}

View File

@@ -0,0 +1,6 @@
import { SaveProgressInfo } from "../../types.js";
import BaseDownloadProgram, { DownloadSlice, ProgramSlice } from "./base-download-program.js";
export default class DownloadProgramChunks extends BaseDownloadProgram {
constructor(savedProgress: SaveProgressInfo, downloadSlice: DownloadSlice);
protected _createOneSlice(): ProgramSlice | null;
}

View File

@@ -0,0 +1,14 @@
import { ChunkStatus } from "../../types.js";
import BaseDownloadProgram from "./base-download-program.js";
export default class DownloadProgramChunks extends BaseDownloadProgram {
constructor(savedProgress, downloadSlice) {
super(savedProgress, downloadSlice);
}
_createOneSlice() {
const notDownloadedIndex = this.savedProgress.chunks.findIndex(c => c === ChunkStatus.NOT_STARTED);
if (notDownloadedIndex === -1)
return null;
return { start: notDownloadedIndex, end: notDownloadedIndex + 1 };
}
}
//# sourceMappingURL=download-program-chunks.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"download-program-chunks.js","sourceRoot":"","sources":["../../../../../src/download/download-engine/download-file/download-programs/download-program-chunks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAmB,MAAM,gBAAgB,CAAC;AAC7D,OAAO,mBAAkD,MAAM,4BAA4B,CAAC;AAE5F,MAAM,CAAC,OAAO,OAAO,qBAAsB,SAAQ,mBAAmB;IAClE,YAAmB,aAA+B,EAAE,aAA4B;QAC5E,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IACxC,CAAC;IAES,eAAe;QACrB,MAAM,kBAAkB,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,WAAW,CAAC,WAAW,CAAC,CAAC;QACnG,IAAI,kBAAkB,KAAK,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAE3C,OAAO,EAAC,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,kBAAkB,GAAG,CAAC,EAAC,CAAC;IACpE,CAAC;CACJ"}

View File

@@ -0,0 +1,7 @@
import { SaveProgressInfo } from "../../types.js";
import BaseDownloadProgram, { DownloadSlice, ProgramSlice } from "./base-download-program.js";
export default class DownloadProgramStream extends BaseDownloadProgram {
constructor(savedProgress: SaveProgressInfo, downloadSlice: DownloadSlice);
protected _createOneSlice(): ProgramSlice | null;
private _findChunksSlices;
}

View File

@@ -0,0 +1,36 @@
import { ChunkStatus } from "../../types.js";
import BaseDownloadProgram from "./base-download-program.js";
export default class DownloadProgramStream extends BaseDownloadProgram {
constructor(savedProgress, downloadSlice) {
super(savedProgress, downloadSlice);
}
_createOneSlice() {
const slice = this._findChunksSlices()[0];
if (!slice)
return null;
const length = slice.end - slice.start;
return { start: Math.floor(slice.start + length / 2), end: slice.end };
}
_findChunksSlices() {
const chunksSlices = [];
let start = 0;
let currentIndex = 0;
for (const chunk of this.savedProgress.chunks) {
if (chunk !== ChunkStatus.NOT_STARTED) {
if (start === currentIndex) {
start = ++currentIndex;
continue;
}
chunksSlices.push({ start, end: currentIndex });
start = ++currentIndex;
continue;
}
currentIndex++;
}
if (start !== currentIndex) {
chunksSlices.push({ start, end: currentIndex });
}
return chunksSlices.sort((a, b) => (b.end - b.start) - (a.end - a.start));
}
}
//# sourceMappingURL=download-program-stream.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"download-program-stream.js","sourceRoot":"","sources":["../../../../../src/download/download-engine/download-file/download-programs/download-program-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAmB,MAAM,gBAAgB,CAAC;AAC7D,OAAO,mBAAkD,MAAM,4BAA4B,CAAC;AAG5F,MAAM,CAAC,OAAO,OAAO,qBAAsB,SAAQ,mBAAmB;IAClE,YAAmB,aAA+B,EAAE,aAA4B;QAC5E,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IACxC,CAAC;IAES,eAAe;QACrB,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC;QACvC,OAAO,EAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAC,CAAC;IACzE,CAAC;IAEO,iBAAiB;QACrB,MAAM,YAAY,GAAmB,EAAE,CAAC;QAExC,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;YAC5C,IAAI,KAAK,KAAK,WAAW,CAAC,WAAW,EAAE,CAAC;gBACpC,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;oBACzB,KAAK,GAAG,EAAE,YAAY,CAAC;oBACvB,SAAS;gBACb,CAAC;gBACD,YAAY,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,GAAG,EAAE,YAAY,EAAC,CAAC,CAAC;gBAC9C,KAAK,GAAG,EAAE,YAAY,CAAC;gBACvB,SAAS;YACb,CAAC;YAED,YAAY,EAAE,CAAC;QACnB,CAAC;QAED,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;YACzB,YAAY,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,GAAG,EAAE,YAAY,EAAC,CAAC,CAAC;QAClD,CAAC;QAED,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9E,CAAC;CACJ"}

View File

@@ -0,0 +1,6 @@
import { SaveProgressInfo } from "../../types.js";
import { DownloadSlice } from "./base-download-program.js";
import DownloadProgramChunks from "./download-program-chunks.js";
import DownloadProgramStream from "./download-program-stream.js";
export type AvailablePrograms = "stream" | "chunks";
export default function switchProgram(savedProgress: SaveProgressInfo, downloadSlice: DownloadSlice, name?: AvailablePrograms): DownloadProgramChunks | DownloadProgramStream;

View File

@@ -0,0 +1,12 @@
import DownloadProgramChunks from "./download-program-chunks.js";
import DownloadProgramStream from "./download-program-stream.js";
export default function switchProgram(savedProgress, downloadSlice, name) {
switch (name) {
case "chunks":
return new DownloadProgramChunks(savedProgress, downloadSlice);
case "stream":
default:
return new DownloadProgramStream(savedProgress, downloadSlice);
}
}
//# sourceMappingURL=switch-program.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"switch-program.js","sourceRoot":"","sources":["../../../../../src/download/download-engine/download-file/download-programs/switch-program.ts"],"names":[],"mappings":"AAEA,OAAO,qBAAqB,MAAM,8BAA8B,CAAC;AACjE,OAAO,qBAAqB,MAAM,8BAA8B,CAAC;AAIjE,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,aAA+B,EAAE,aAA4B,EAAE,IAAwB;IACzH,QAAQ,IAAI,EAAE,CAAC;QACX,KAAK,QAAQ;YACT,OAAO,IAAI,qBAAqB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;QACnE,KAAK,QAAQ,CAAC;QACd;YACI,OAAO,IAAI,qBAAqB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IACvE,CAAC;AACL,CAAC"}