Compare commits

..

No commits in common. "5569c690a150ae23c6abcffa16fd613092ace962" and "8f077868cc5a34207ff473a18357cad67a2e76a3" have entirely different histories.

4 changed files with 10 additions and 56 deletions

View File

@ -78,7 +78,7 @@ class DoodstreamUploader {
/** /**
* Login to DoodStream via web form * Login to DoodStream via web form
*/ */
async login(username, password, otp) { async login(username, password) {
// GET homepage first to collect cookies // GET homepage first to collect cookies
const homeRes = await this._fetch(BASE_URL); const homeRes = await this._fetch(BASE_URL);
await homeRes.text(); await homeRes.text();
@ -88,7 +88,7 @@ class DoodstreamUploader {
op: 'login_ajax', op: 'login_ajax',
login: username, login: username,
password: password, password: password,
loginotp: otp || '' loginotp: ''
}); });
// Use raw fetch with redirect: 'manual' to detect success redirects // Use raw fetch with redirect: 'manual' to detect success redirects
@ -122,11 +122,6 @@ class DoodstreamUploader {
if (json && json.status === 'success') { if (json && json.status === 'success') {
// Explicit success response // Explicit success response
} else if (json && json.message && /otp/i.test(json.message)) {
// OTP required — signal caller to collect OTP from user
const err = new Error(`Doodstream Login: ${json.message}`);
err.otpRequired = true;
throw err;
} else if (json && json.status === 'fail') { } else if (json && json.status === 'fail') {
throw new Error(`Doodstream Login: ${json.message || 'Login fehlgeschlagen'}`); throw new Error(`Doodstream Login: ${json.message || 'Login fehlgeschlagen'}`);
} else if (body.includes('Dashboard')) { } else if (body.includes('Dashboard')) {

15
main.js
View File

@ -188,7 +188,7 @@ function buildUploadTasksFromJobs(config, jobs) {
}); });
} }
async function checkDoodstreamHealth(hosterConfig, otp) { async function checkDoodstreamHealth(hosterConfig) {
const username = hosterConfig && hosterConfig.username const username = hosterConfig && hosterConfig.username
? String(hosterConfig.username).trim() ? String(hosterConfig.username).trim()
: ''; : '';
@ -199,14 +199,7 @@ async function checkDoodstreamHealth(hosterConfig, otp) {
// Login-based check (preferred) // Login-based check (preferred)
if (username && password) { if (username && password) {
const uploader = new DoodstreamUploader(); const uploader = new DoodstreamUploader();
try { await uploader.login(username, password);
await uploader.login(username, password, otp || undefined);
} catch (err) {
if (err.otpRequired) {
return { status: 'otp_required', message: err.message || 'OTP erforderlich' };
}
throw err;
}
return { status: 'ok', message: 'Login ok, Upload-Seite bereit' }; return { status: 'ok', message: 'Login ok, Upload-Seite bereit' };
} }
@ -409,7 +402,7 @@ async function runHosterHealthCheck(config, requestedChecks) {
checks = requestedChecks; checks = requestedChecks;
} }
const results = await Promise.all(checks.map(async ({ hoster, accountId, otp }) => { const results = await Promise.all(checks.map(async ({ hoster, accountId }) => {
if (!allowed.includes(hoster)) { if (!allowed.includes(hoster)) {
return { hoster, accountId, status: 'skipped', message: 'Kein Health-Check fuer diesen Hoster' }; return { hoster, accountId, status: 'skipped', message: 'Kein Health-Check fuer diesen Hoster' };
} }
@ -421,7 +414,7 @@ async function runHosterHealthCheck(config, requestedChecks) {
try { try {
let result; let result;
if (hoster === 'doodstream.com') { if (hoster === 'doodstream.com') {
result = await withTimeout(checkDoodstreamHealth(hosterConfig, otp), HEALTH_CHECK_TIMEOUT, 'Doodstream-Check'); result = await withTimeout(checkDoodstreamHealth(hosterConfig), HEALTH_CHECK_TIMEOUT, 'Doodstream-Check');
} else if (hoster === 'vidmoly.me') { } else if (hoster === 'vidmoly.me') {
result = await withTimeout(checkVidmolyHealth(hosterConfig), HEALTH_CHECK_TIMEOUT, 'Vidmoly-Check'); result = await withTimeout(checkVidmolyHealth(hosterConfig), HEALTH_CHECK_TIMEOUT, 'Vidmoly-Check');
} else if (hoster === 'voe.sx') { } else if (hoster === 'voe.sx') {

View File

@ -1,6 +1,6 @@
{ {
"name": "multi-hoster-uploader", "name": "multi-hoster-uploader",
"version": "2.2.0", "version": "2.1.9",
"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": {

View File

@ -2627,7 +2627,6 @@ function openAccountModal(editAccountId) {
function closeAccountModal() { function closeAccountModal() {
document.getElementById('accountModal').style.display = 'none'; document.getElementById('accountModal').style.display = 'none';
_hideOtpField();
editingAccountId = null; editingAccountId = null;
} }
@ -2735,30 +2734,15 @@ async function saveAccount() {
renderHosterModal(); renderHosterModal();
renderSettings(); renderSettings();
// Check if OTP was entered (for retry after OTP prompt) // Run health check for this specific account
const otpInput = document.getElementById('accField_otp');
const otp = otpInput ? otpInput.value.trim() : '';
// Run health check for this specific account (include OTP if provided)
const checkPayload = { hoster: hosterName, accountId };
if (otp) checkPayload.otp = otp;
try { try {
const result = await window.api.runHealthCheck({ hosters: [checkPayload] }); const result = await window.api.runHealthCheck({ hosters: [{ hoster: hosterName, accountId }] });
const rows = result && Array.isArray(result.results) ? result.results : []; const rows = result && Array.isArray(result.results) ? result.results : [];
const row = rows.find(r => r.accountId === accountId); const row = rows.find(r => r.accountId === accountId);
if (row && row.status === 'otp_required') { if (row && (row.status === 'ok' || row.status === 'warn')) {
// Show OTP input field if not already visible
accountStatuses[accountId] = { status: 'error', message: row.message || 'OTP erforderlich' };
statusEl.textContent = row.message || 'OTP wurde an deine E-Mail gesendet.';
statusEl.className = 'account-modal-status error';
_showOtpField();
saveBtn.textContent = 'OTP bestätigen';
} else if (row && (row.status === 'ok' || row.status === 'warn')) {
accountStatuses[accountId] = { status: row.status || 'ok', message: row.message || '' }; accountStatuses[accountId] = { status: row.status || 'ok', message: row.message || '' };
statusEl.textContent = row.status === 'warn' ? row.message || 'Prüfung mit Warnung abgeschlossen.' : 'Login erfolgreich!'; statusEl.textContent = row.status === 'warn' ? row.message || 'Prüfung mit Warnung abgeschlossen.' : 'Login erfolgreich!';
statusEl.className = 'account-modal-status ok'; statusEl.className = 'account-modal-status ok';
_hideOtpField();
setTimeout(() => closeAccountModal(), 1200); setTimeout(() => closeAccountModal(), 1200);
} else { } else {
const msg = (row && row.message) || 'Login fehlgeschlagen'; const msg = (row && row.message) || 'Login fehlgeschlagen';
@ -2780,24 +2764,6 @@ async function saveAccount() {
} }
} }
function _showOtpField() {
if (document.getElementById('accField_otp')) return; // already visible
const container = document.getElementById('accountCredsFields');
const otpHtml = `
<div class="settings-row" id="otpFieldRow">
<label>OTP Code</label>
<input type="text" class="key-input" id="accField_otp" placeholder="6-stelliger Code aus E-Mail" autocomplete="one-time-code" inputmode="numeric" maxlength="10">
</div>`;
container.insertAdjacentHTML('beforeend', otpHtml);
// Auto-focus the OTP field
setTimeout(() => document.getElementById('accField_otp')?.focus(), 50);
}
function _hideOtpField() {
const row = document.getElementById('otpFieldRow');
if (row) row.remove();
}
// --- History --- // --- History ---
async function loadHistory() { async function loadHistory() {
const history = await window.api.getHistory(); const history = await window.api.getHistory();