Compare commits
2 Commits
8f077868cc
...
5569c690a1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5569c690a1 | ||
|
|
beba96c21b |
@ -78,7 +78,7 @@ class DoodstreamUploader {
|
|||||||
/**
|
/**
|
||||||
* Login to DoodStream via web form
|
* Login to DoodStream via web form
|
||||||
*/
|
*/
|
||||||
async login(username, password) {
|
async login(username, password, otp) {
|
||||||
// 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: ''
|
loginotp: otp || ''
|
||||||
});
|
});
|
||||||
|
|
||||||
// Use raw fetch with redirect: 'manual' to detect success redirects
|
// Use raw fetch with redirect: 'manual' to detect success redirects
|
||||||
@ -122,6 +122,11 @@ 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
15
main.js
@ -188,7 +188,7 @@ function buildUploadTasksFromJobs(config, jobs) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkDoodstreamHealth(hosterConfig) {
|
async function checkDoodstreamHealth(hosterConfig, otp) {
|
||||||
const username = hosterConfig && hosterConfig.username
|
const username = hosterConfig && hosterConfig.username
|
||||||
? String(hosterConfig.username).trim()
|
? String(hosterConfig.username).trim()
|
||||||
: '';
|
: '';
|
||||||
@ -199,7 +199,14 @@ async function checkDoodstreamHealth(hosterConfig) {
|
|||||||
// Login-based check (preferred)
|
// Login-based check (preferred)
|
||||||
if (username && password) {
|
if (username && password) {
|
||||||
const uploader = new DoodstreamUploader();
|
const uploader = new DoodstreamUploader();
|
||||||
await uploader.login(username, password);
|
try {
|
||||||
|
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' };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,7 +409,7 @@ async function runHosterHealthCheck(config, requestedChecks) {
|
|||||||
checks = requestedChecks;
|
checks = requestedChecks;
|
||||||
}
|
}
|
||||||
|
|
||||||
const results = await Promise.all(checks.map(async ({ hoster, accountId }) => {
|
const results = await Promise.all(checks.map(async ({ hoster, accountId, otp }) => {
|
||||||
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' };
|
||||||
}
|
}
|
||||||
@ -414,7 +421,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), HEALTH_CHECK_TIMEOUT, 'Doodstream-Check');
|
result = await withTimeout(checkDoodstreamHealth(hosterConfig, otp), 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') {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "multi-hoster-uploader",
|
"name": "multi-hoster-uploader",
|
||||||
"version": "2.1.9",
|
"version": "2.2.0",
|
||||||
"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": {
|
||||||
|
|||||||
@ -2627,6 +2627,7 @@ function openAccountModal(editAccountId) {
|
|||||||
|
|
||||||
function closeAccountModal() {
|
function closeAccountModal() {
|
||||||
document.getElementById('accountModal').style.display = 'none';
|
document.getElementById('accountModal').style.display = 'none';
|
||||||
|
_hideOtpField();
|
||||||
editingAccountId = null;
|
editingAccountId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2734,15 +2735,30 @@ async function saveAccount() {
|
|||||||
renderHosterModal();
|
renderHosterModal();
|
||||||
renderSettings();
|
renderSettings();
|
||||||
|
|
||||||
// Run health check for this specific account
|
// Check if OTP was entered (for retry after OTP prompt)
|
||||||
|
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: [{ hoster: hosterName, accountId }] });
|
const result = await window.api.runHealthCheck({ hosters: [checkPayload] });
|
||||||
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 === 'ok' || row.status === 'warn')) {
|
if (row && row.status === 'otp_required') {
|
||||||
|
// 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';
|
||||||
@ -2764,6 +2780,24 @@ 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();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user