Compare commits
No commits in common. "e02926e849db6d3b7b4bb7b2b6661021a32461e5" and "00bf6f126dcc47d64db8924986391a8a27baeb02" have entirely different histories.
e02926e849
...
00bf6f126d
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "multi-hoster-uploader",
|
"name": "multi-hoster-uploader",
|
||||||
"version": "2.6.7",
|
"version": "2.6.6",
|
||||||
"description": "Upload files to doodstream, voe, vidmoly, byse simultaneously",
|
"description": "Upload files to doodstream, voe, vidmoly, byse simultaneously",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -119,24 +119,10 @@ async function init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newFiles.length > 0) {
|
if (newFiles.length > 0) {
|
||||||
const newPaths = new Set(newFiles.map(f => f.path));
|
|
||||||
selectedFiles.push(...newFiles);
|
selectedFiles.push(...newFiles);
|
||||||
buildQueuePreview();
|
buildQueuePreview();
|
||||||
updateUploadView();
|
updateUploadView();
|
||||||
if (fm.autoStart && !uploading && !healthCheckRunning) {
|
if (fm.autoStart && !uploading && !healthCheckRunning) startUpload();
|
||||||
startUpload();
|
|
||||||
} else if (uploading) {
|
|
||||||
// Inject new preview jobs into the running batch
|
|
||||||
const newJobs = queueJobs.filter(j => j.status === 'preview' && newPaths.has(j.file));
|
|
||||||
if (newJobs.length > 0) {
|
|
||||||
newJobs.forEach(j => { j.status = 'queued'; });
|
|
||||||
renderQueueTable();
|
|
||||||
window.api.addJobsToBatch({
|
|
||||||
jobs: newJobs.map(j => ({ id: j.id, file: j.file, fileName: j.fileName, hoster: j.hoster }))
|
|
||||||
}).then(result => { _markSkippedJobs(result); }).catch(() => {});
|
|
||||||
persistQueueStateSoon(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// No pre-selected hosters: open modal
|
// No pre-selected hosters: open modal
|
||||||
@ -374,29 +360,11 @@ function applyHosterSelection() {
|
|||||||
selectedUploadHosters = Array.from(document.querySelectorAll('input[data-hoster-modal]:checked'))
|
selectedUploadHosters = Array.from(document.querySelectorAll('input[data-hoster-modal]:checked'))
|
||||||
.map(input => input.dataset.hosterModal);
|
.map(input => input.dataset.hosterModal);
|
||||||
// Move pending files to selectedFiles on confirm
|
// Move pending files to selectedFiles on confirm
|
||||||
const pendingPaths = new Set(_pendingFiles.map(f => f.path));
|
|
||||||
if (_pendingFiles.length > 0) {
|
if (_pendingFiles.length > 0) {
|
||||||
selectedFiles.push(..._pendingFiles);
|
selectedFiles.push(..._pendingFiles);
|
||||||
_pendingFiles = [];
|
_pendingFiles = [];
|
||||||
}
|
}
|
||||||
renderHosterSummary();
|
renderHosterSummary();
|
||||||
|
|
||||||
// During an active upload, build preview jobs for the new files and inject
|
|
||||||
// them into the running batch immediately (otherwise they'd be lost on
|
|
||||||
// handleBatchDone via syncSelectedFilesFromQueue)
|
|
||||||
if (uploading && pendingPaths.size > 0) {
|
|
||||||
buildQueuePreview(); // creates 'preview' jobs for new files
|
|
||||||
const newJobs = queueJobs.filter(j => j.status === 'preview' && pendingPaths.has(j.file));
|
|
||||||
if (newJobs.length > 0) {
|
|
||||||
newJobs.forEach(j => { j.status = 'queued'; });
|
|
||||||
renderQueueTable();
|
|
||||||
window.api.addJobsToBatch({
|
|
||||||
jobs: newJobs.map(j => ({ id: j.id, file: j.file, fileName: j.fileName, hoster: j.hoster }))
|
|
||||||
}).then(result => { _markSkippedJobs(result); }).catch(() => {});
|
|
||||||
persistQueueStateSoon(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateUploadView();
|
updateUploadView();
|
||||||
persistQueueStateSoon(true); // immediate persist after adding files
|
persistQueueStateSoon(true); // immediate persist after adding files
|
||||||
document.getElementById('hosterModal').style.display = 'none';
|
document.getElementById('hosterModal').style.display = 'none';
|
||||||
|
|||||||
@ -409,75 +409,6 @@ describe('UploadManager', () => {
|
|||||||
assert.ok(maxConcurrent <= 2, `scaleParallelUploads should cap at 2, was ${maxConcurrent}`);
|
assert.ok(maxConcurrent <= 2, `scaleParallelUploads should cap at 2, was ${maxConcurrent}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('addJobs injects new tasks into running batch', async () => {
|
|
||||||
let started = 0;
|
|
||||||
mockUploadFile.mock.mockImplementation(async (hoster, filePath, apiKey, onProgress) => {
|
|
||||||
started++;
|
|
||||||
await new Promise(r => setTimeout(r, 100));
|
|
||||||
if (onProgress) onProgress(fakeFileSize, fakeFileSize);
|
|
||||||
return { download_url: 'ok', embed_url: null, file_code: 'ok' };
|
|
||||||
});
|
|
||||||
|
|
||||||
const mgr = new UploadManager({});
|
|
||||||
let summary = null;
|
|
||||||
mgr.on('batch-done', (s) => { summary = s; });
|
|
||||||
|
|
||||||
// Start batch with 2 tasks
|
|
||||||
const batchPromise = mgr.startBatch([
|
|
||||||
{ jobId: 'job-1', file: '/test/a.mp4', hoster: 'doodstream.com', apiKey: 'k' },
|
|
||||||
{ jobId: 'job-2', file: '/test/b.mp4', hoster: 'doodstream.com', apiKey: 'k' }
|
|
||||||
]);
|
|
||||||
|
|
||||||
// After 30ms (during upload), inject 2 more tasks
|
|
||||||
await new Promise(r => setTimeout(r, 30));
|
|
||||||
const result = mgr.addJobs([
|
|
||||||
{ jobId: 'job-3', file: '/test/c.mp4', hoster: 'doodstream.com', apiKey: 'k' },
|
|
||||||
{ jobId: 'job-4', file: '/test/d.mp4', hoster: 'doodstream.com', apiKey: 'k' }
|
|
||||||
]);
|
|
||||||
assert.equal(result.added, 2, 'should add 2 new jobs');
|
|
||||||
assert.equal(result.alreadyInBatchJobIds.length, 0);
|
|
||||||
|
|
||||||
await batchPromise;
|
|
||||||
assert.ok(summary);
|
|
||||||
assert.equal(started, 4, 'all 4 jobs should have run');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('addJobs rejects duplicates already in running batch', async () => {
|
|
||||||
mockUploadFile.mock.mockImplementation(async (hoster, filePath, apiKey, onProgress, signal) => {
|
|
||||||
// Slow upload so we can add jobs while it's running
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
const timer = setTimeout(resolve, 200);
|
|
||||||
if (signal) signal.addEventListener('abort', () => { clearTimeout(timer); reject(new Error('Aborted')); });
|
|
||||||
});
|
|
||||||
if (onProgress) onProgress(fakeFileSize, fakeFileSize);
|
|
||||||
return { download_url: 'ok', embed_url: null, file_code: 'ok' };
|
|
||||||
});
|
|
||||||
|
|
||||||
const mgr = new UploadManager({});
|
|
||||||
const batchPromise = mgr.startBatch([
|
|
||||||
{ jobId: 'job-A', file: '/test/x.mp4', hoster: 'doodstream.com', apiKey: 'k' }
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Try to add the SAME jobId while it's running
|
|
||||||
await new Promise(r => setTimeout(r, 50));
|
|
||||||
const result = mgr.addJobs([
|
|
||||||
{ jobId: 'job-A', file: '/test/x.mp4', hoster: 'doodstream.com', apiKey: 'k' },
|
|
||||||
{ jobId: 'job-B', file: '/test/y.mp4', hoster: 'doodstream.com', apiKey: 'k' }
|
|
||||||
]);
|
|
||||||
assert.equal(result.added, 1, 'should skip duplicate jobId, add only the new one');
|
|
||||||
assert.deepEqual(result.alreadyInBatchJobIds, ['job-A']);
|
|
||||||
|
|
||||||
await batchPromise;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('addJobs returns added=0 when not running', () => {
|
|
||||||
const mgr = new UploadManager({});
|
|
||||||
const result = mgr.addJobs([
|
|
||||||
{ jobId: 'job-1', file: '/test/a.mp4', hoster: 'doodstream.com', apiKey: 'k' }
|
|
||||||
]);
|
|
||||||
assert.equal(result.added, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('stats event contains expected fields', async () => {
|
it('stats event contains expected fields', async () => {
|
||||||
// Make upload take long enough for stats interval to fire
|
// Make upload take long enough for stats interval to fire
|
||||||
mockUploadFile.mock.mockImplementation(async (hoster, filePath, apiKey, onProgress, signal) => {
|
mockUploadFile.mock.mockImplementation(async (hoster, filePath, apiKey, onProgress, signal) => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user