Compare commits
2 Commits
6286bca7c6
...
d2f903b8ba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2f903b8ba | ||
|
|
fc48f20db5 |
@ -446,6 +446,54 @@ async function _resolveByseUploadByName(apiKey, fileName, baselineCodes, signal)
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function _fetchDoodstreamFileList(apiKey, signal) {
|
||||||
|
// doodapi.co file list: { msg, status:200, result: { files: [{ file_code, title, uploaded, ... }] } }
|
||||||
|
const url = `https://doodapi.co/api/file/list?key=${encodeURIComponent(apiKey)}&per_page=200`;
|
||||||
|
try {
|
||||||
|
const { body, statusCode } = await request(url, {
|
||||||
|
method: 'GET', signal,
|
||||||
|
headers: { 'Accept': 'application/json', 'User-Agent': 'multi-hoster-uploader/1.1' },
|
||||||
|
headersTimeout: 30_000, bodyTimeout: 30_000
|
||||||
|
});
|
||||||
|
const text = await body.text();
|
||||||
|
if (statusCode < 200 || statusCode >= 300) return [];
|
||||||
|
const data = JSON.parse(text);
|
||||||
|
const files = data && data.result && Array.isArray(data.result.files) ? data.result.files : [];
|
||||||
|
return files.map(f => ({
|
||||||
|
file_code: String(f.file_code || f.filecode || '').trim(),
|
||||||
|
file_name: String(f.title || f.file_name || f.name || '').trim()
|
||||||
|
})).filter(f => f.file_code);
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function _resolveDoodstreamUploadByName(apiKey, fileName, baselineCodes, signal) {
|
||||||
|
// Same recovery byse uses: the upload POST returned no filecode, but the file
|
||||||
|
// may register in the account a little later. Poll the list for a NEW file
|
||||||
|
// whose normalized title matches what we uploaded. Exact-name match only
|
||||||
|
// (never "take the only new one") so parallel doodstream uploads can't claim
|
||||||
|
// each other's files.
|
||||||
|
const expected = _normalizeFileTitle(fileName);
|
||||||
|
const POLL_ATTEMPTS = 12;
|
||||||
|
const POLL_DELAY_MS = 2500;
|
||||||
|
for (let i = 0; i < POLL_ATTEMPTS; i++) {
|
||||||
|
if (signal && signal.aborted) return null;
|
||||||
|
const list = await _fetchDoodstreamFileList(apiKey, signal);
|
||||||
|
const fresh = list.filter(f => !baselineCodes.has(f.file_code));
|
||||||
|
const match = fresh.find(f => _normalizeFileTitle(f.file_name) === expected);
|
||||||
|
if (match) {
|
||||||
|
return {
|
||||||
|
download_url: `https://doodstream.com/d/${match.file_code}`,
|
||||||
|
embed_url: `https://doodstream.com/e/${match.file_code}`,
|
||||||
|
file_code: match.file_code
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (i < POLL_ATTEMPTS - 1) await sleep(POLL_DELAY_MS, signal);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
async function uploadFile(hosterName, filePath, apiKey, onProgress, signal, throttle) {
|
async function uploadFile(hosterName, filePath, apiKey, onProgress, signal, throttle) {
|
||||||
const config = HOSTER_CONFIGS[hosterName];
|
const config = HOSTER_CONFIGS[hosterName];
|
||||||
if (!config) throw new Error(`Unbekannter Hoster: ${hosterName}`);
|
if (!config) throw new Error(`Unbekannter Hoster: ${hosterName}`);
|
||||||
@ -458,6 +506,13 @@ async function uploadFile(hosterName, filePath, apiKey, onProgress, signal, thro
|
|||||||
const baseline = await _fetchByseFileList(apiKey, signal);
|
const baseline = await _fetchByseFileList(apiKey, signal);
|
||||||
byseBaseline = new Set(baseline.map(f => f.file_code));
|
byseBaseline = new Set(baseline.map(f => f.file_code));
|
||||||
}
|
}
|
||||||
|
// Doodstream: same snapshot so a codeless upload response can be recovered by
|
||||||
|
// matching a newly-appeared file in the account by name (see below).
|
||||||
|
let doodBaseline = null;
|
||||||
|
if (hosterName === 'doodstream.com') {
|
||||||
|
const baseline = await _fetchDoodstreamFileList(apiKey, signal);
|
||||||
|
doodBaseline = new Set(baseline.map(f => f.file_code));
|
||||||
|
}
|
||||||
|
|
||||||
// Step 1: Get upload server
|
// Step 1: Get upload server
|
||||||
const uploadUrl = await getUploadServer(hosterName, config, apiKey, signal);
|
const uploadUrl = await getUploadServer(hosterName, config, apiKey, signal);
|
||||||
@ -537,6 +592,15 @@ async function uploadFile(hosterName, filePath, apiKey, onProgress, signal, thro
|
|||||||
if (polled) return polled;
|
if (polled) return polled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Doodstream: the doodapi upload POST returned no filecode (the same backend
|
||||||
|
// hiccup that empties the web form). Poll the account file list by name — if
|
||||||
|
// the file did register, claim its code instead of failing the upload.
|
||||||
|
if (hosterName === 'doodstream.com' && doodBaseline) {
|
||||||
|
const fileName = path.basename(filePath);
|
||||||
|
const polled = await _resolveDoodstreamUploadByName(apiKey, fileName, doodBaseline, signal);
|
||||||
|
if (polled) return polled;
|
||||||
|
}
|
||||||
|
|
||||||
if (parseErr) throw parseErr;
|
if (parseErr) throw parseErr;
|
||||||
|
|
||||||
if (payload.success === false) {
|
if (payload.success === false) {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "multi-hoster-uploader",
|
"name": "multi-hoster-uploader",
|
||||||
"version": "3.3.31",
|
"version": "3.3.32",
|
||||||
"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": {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user