fix(voe): use 2-step CDN upload flow + add health check
This commit is contained in:
parent
71e9232269
commit
34fbfcb016
@ -141,7 +141,7 @@ class VoeUploader {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the upload page and extract CSRF token + any upload params
|
||||
* Get the upload page and extract CSRF token
|
||||
*/
|
||||
async _getUploadParams() {
|
||||
const res = await this._fetch(`${BASE_URL}/file-upload`);
|
||||
@ -155,6 +155,28 @@ class VoeUploader {
|
||||
return { csrfToken };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get upload server URL from /engine/delivery-node
|
||||
* Returns { server: "https://cdn-xxx.edgeon-bandwidth.com/node/u/01", session_id: "..." }
|
||||
*/
|
||||
async _getDeliveryNode(csrfToken) {
|
||||
const res = await this._fetch(`${BASE_URL}/engine/delivery-node`, {
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': csrfToken,
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
const body = await res.text();
|
||||
const data = JSON.parse(body);
|
||||
|
||||
if (!data || !data.success || !data.server) {
|
||||
throw new Error('VOE: Kein Upload-Server erhalten von delivery-node');
|
||||
}
|
||||
|
||||
return { uploadServer: data.server, sessionId: data.session_id || '' };
|
||||
}
|
||||
|
||||
/**
|
||||
* List current files via VOE API (for result polling fallback)
|
||||
*/
|
||||
@ -182,18 +204,29 @@ class VoeUploader {
|
||||
|
||||
/**
|
||||
* Upload a file to VOE.sx via login session
|
||||
* Flow: GET delivery-node → POST file to CDN server
|
||||
*/
|
||||
async upload(filePath, onProgress, signal, throttle) {
|
||||
const fileName = path.basename(filePath);
|
||||
const fileSize = fs.statSync(filePath).size;
|
||||
const baselineCodes = await this._captureFileCodes();
|
||||
|
||||
// Step 1: Get CSRF token from upload page
|
||||
const { csrfToken } = await this._getUploadParams();
|
||||
|
||||
// Step 2: Get CDN upload server from delivery-node
|
||||
const { uploadServer, sessionId } = await this._getDeliveryNode(csrfToken);
|
||||
|
||||
const boundary = '----FormBoundary' + crypto.randomBytes(16).toString('hex');
|
||||
|
||||
// Build multipart body
|
||||
let preamble = '';
|
||||
// Include session_id if provided
|
||||
if (sessionId) {
|
||||
preamble += `--${boundary}\r\n`;
|
||||
preamble += `Content-Disposition: form-data; name="session_id"\r\n\r\n`;
|
||||
preamble += `${sessionId}\r\n`;
|
||||
}
|
||||
preamble += `--${boundary}\r\n`;
|
||||
preamble += `Content-Disposition: form-data; name="file"; filename="${fileName}"\r\n`;
|
||||
preamble += `Content-Type: application/octet-stream\r\n\r\n`;
|
||||
@ -219,10 +252,8 @@ class VoeUploader {
|
||||
yield epilogueBuf;
|
||||
}
|
||||
|
||||
// POST to /engine/delivery-node
|
||||
const uploadUrl = `${BASE_URL}/engine/delivery-node`;
|
||||
|
||||
const { body, statusCode, headers } = await request(uploadUrl, {
|
||||
// Step 3: POST file to CDN upload server
|
||||
const { body, statusCode, headers } = await request(uploadServer, {
|
||||
method: 'POST',
|
||||
body: generate(),
|
||||
signal,
|
||||
|
||||
54
main.js
54
main.js
@ -202,8 +202,51 @@ async function checkVidmolyHealth(hosterConfig) {
|
||||
};
|
||||
}
|
||||
|
||||
async function checkVoeHealth(hosterConfig) {
|
||||
const username = hosterConfig && hosterConfig.username
|
||||
? String(hosterConfig.username).trim()
|
||||
: '';
|
||||
const password = hosterConfig && hosterConfig.password
|
||||
? String(hosterConfig.password).trim()
|
||||
: '';
|
||||
|
||||
if (!username || !password) {
|
||||
// Fall back to API key check if no login
|
||||
const apiKey = hosterConfig && hosterConfig.apiKey
|
||||
? String(hosterConfig.apiKey).trim()
|
||||
: '';
|
||||
if (!apiKey) {
|
||||
return { status: 'error', message: 'Login oder API Key fehlt' };
|
||||
}
|
||||
// Quick API check
|
||||
const res = await fetch(`https://voe.sx/api/upload/server?key=${encodeURIComponent(apiKey)}`, { method: 'GET' });
|
||||
const data = await res.json().catch(() => null);
|
||||
if (data && data.result && typeof data.result === 'string' && /^https?:\/\//i.test(data.result.trim())) {
|
||||
return { status: 'ok', message: 'API Key gueltig, Upload-Server verfuegbar' };
|
||||
}
|
||||
const msg = data && (data.msg || data.message) ? String(data.msg || data.message).trim() : '';
|
||||
if (/no servers/i.test(msg)) {
|
||||
return { status: 'warn', message: 'API Key gueltig, aktuell kein Server verfuegbar' };
|
||||
}
|
||||
return { status: 'error', message: msg || 'API Key ungueltig oder Server nicht erreichbar' };
|
||||
}
|
||||
|
||||
const uploader = new VoeUploader();
|
||||
await uploader.login(username, password);
|
||||
const { csrfToken } = await uploader._getUploadParams();
|
||||
|
||||
if (!csrfToken) {
|
||||
return { status: 'error', message: 'Login ok, aber Upload-Seite liefert kein CSRF-Token' };
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'ok',
|
||||
message: 'Login ok, Upload-Seite bereit'
|
||||
};
|
||||
}
|
||||
|
||||
async function runHosterHealthCheck(config, requestedHosters) {
|
||||
const allowed = ['doodstream.com', 'vidmoly.me'];
|
||||
const allowed = ['doodstream.com', 'vidmoly.me', 'voe.sx'];
|
||||
const source = Array.isArray(requestedHosters) && requestedHosters.length > 0
|
||||
? requestedHosters
|
||||
: allowed;
|
||||
@ -238,6 +281,15 @@ async function runHosterHealthCheck(config, requestedHosters) {
|
||||
return { hoster, ...result };
|
||||
}
|
||||
|
||||
if (hoster === 'voe.sx') {
|
||||
const result = await withTimeout(
|
||||
checkVoeHealth(hosterConfig),
|
||||
HEALTH_CHECK_TIMEOUT,
|
||||
'VOE-Check'
|
||||
);
|
||||
return { hoster, ...result };
|
||||
}
|
||||
|
||||
return { hoster, status: 'skipped', message: 'Kein Health-Check fuer diesen Hoster' };
|
||||
} catch (err) {
|
||||
return {
|
||||
|
||||
@ -652,7 +652,7 @@ async function startUpload() {
|
||||
|
||||
// Auto health check
|
||||
if (autoHealthCheckEnabled) {
|
||||
const checkHosters = hosters.filter(name => name === 'doodstream.com' || name === 'vidmoly.me');
|
||||
const checkHosters = hosters.filter(name => name === 'doodstream.com' || name === 'vidmoly.me' || name === 'voe.sx');
|
||||
if (checkHosters.length > 0) {
|
||||
healthCheckRunning = true;
|
||||
try {
|
||||
@ -850,9 +850,9 @@ async function executeHealthCheck(hosters, mode) {
|
||||
|
||||
async function runHealthCheck() {
|
||||
if (healthCheckRunning || uploading) return;
|
||||
const hosters = getSelectedHosters().filter(n => n === 'doodstream.com' || n === 'vidmoly.me');
|
||||
const hosters = getSelectedHosters().filter(n => n === 'doodstream.com' || n === 'vidmoly.me' || n === 'voe.sx');
|
||||
if (hosters.length === 0) {
|
||||
const allHosters = ['doodstream.com', 'vidmoly.me'].filter(n => hosterHasCredentials(n, config.hosters[n] || {}));
|
||||
const allHosters = ['doodstream.com', 'vidmoly.me', 'voe.sx'].filter(n => hosterHasCredentials(n, config.hosters[n] || {}));
|
||||
if (allHosters.length === 0) { alert('Keine Hoster mit Zugangsdaten fuer Health-Check.'); return; }
|
||||
hosters.push(...allHosters);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user