fix: doodstream login redirect handling + queue only adds files after confirm
- Fix doodstream login: handle redirect on success (server returns HTML dashboard instead of JSON) - Fix sess_id extraction: match hidden input field format - Files are now only added to queue after clicking "Uebernehmen" in hoster modal - Cancel/Escape/click-outside discards pending files Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d94156943b
commit
b8b8158abb
@ -84,24 +84,46 @@ class DoodstreamUploader {
|
||||
loginotp: ''
|
||||
});
|
||||
|
||||
const res = await this._fetch(BASE_URL + '/', {
|
||||
method: 'POST',
|
||||
body: loginData.toString(),
|
||||
headers: {
|
||||
// Use raw fetch with redirect: 'manual' to detect success redirects
|
||||
const headers = {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Referer': BASE_URL + '/',
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
'User-Agent': USER_AGENT
|
||||
};
|
||||
if (this.cookies.size > 0) {
|
||||
headers['Cookie'] = this._cookieHeader();
|
||||
}
|
||||
|
||||
const res = await fetch(BASE_URL + '/', {
|
||||
method: 'POST',
|
||||
body: loginData.toString(),
|
||||
headers,
|
||||
redirect: 'manual'
|
||||
});
|
||||
|
||||
this._parseCookiesFromHeaders(res.headers);
|
||||
|
||||
// On successful login, server may redirect (3xx) to dashboard
|
||||
if ([301, 302, 303, 307, 308].includes(res.status)) {
|
||||
try { await res.text(); } catch {}
|
||||
// Redirect means login succeeded
|
||||
} else {
|
||||
const body = await res.text();
|
||||
let json;
|
||||
try { json = JSON.parse(body); } catch { json = null; }
|
||||
|
||||
if (!json || json.status !== 'success') {
|
||||
if (json && json.status === 'success') {
|
||||
// Explicit success response
|
||||
} else if (json && json.status === 'fail') {
|
||||
throw new Error(`Doodstream Login: ${json.message || 'Login fehlgeschlagen'}`);
|
||||
} else if (body.includes('Dashboard')) {
|
||||
// Got dashboard HTML directly — login worked
|
||||
} else {
|
||||
const msg = (json && json.message) || 'Login fehlgeschlagen';
|
||||
throw new Error(`Doodstream Login: ${msg}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Extract sess_id from the upload page
|
||||
await this._extractSessId();
|
||||
@ -111,14 +133,21 @@ class DoodstreamUploader {
|
||||
const res = await this._fetch(BASE_URL + '/?op=upload');
|
||||
const html = await res.text();
|
||||
|
||||
// Look for sess_id in the page (Vue component prop or hidden field)
|
||||
// Hidden input: <input type="hidden" name="sess_id" value="xxx">
|
||||
const hiddenMatch = html.match(/name=["']sess_id["'][^>]*value=["']([a-zA-Z0-9]+)["']/);
|
||||
if (hiddenMatch) {
|
||||
this.sessId = hiddenMatch[1];
|
||||
return;
|
||||
}
|
||||
|
||||
// Vue component prop or JS: sess_id: "xxx" or sess_id="xxx"
|
||||
const sessMatch = html.match(/sess_id['":\s]+['"]([a-zA-Z0-9]+)['"]/);
|
||||
if (sessMatch) {
|
||||
this.sessId = sessMatch[1];
|
||||
return;
|
||||
}
|
||||
|
||||
// Alternative: look in script or data attributes
|
||||
// Assignment: sess_id = 'xxx'
|
||||
const altMatch = html.match(/sess_id\s*=\s*['"]([a-zA-Z0-9]+)['"]/);
|
||||
if (altMatch) {
|
||||
this.sessId = altMatch[1];
|
||||
|
||||
@ -193,10 +193,19 @@ function closeHosterModal() {
|
||||
function applyHosterSelection() {
|
||||
selectedUploadHosters = Array.from(document.querySelectorAll('input[data-hoster-modal]:checked'))
|
||||
.map(input => input.dataset.hosterModal);
|
||||
// Move pending files to selectedFiles on confirm
|
||||
if (_pendingFiles.length > 0) {
|
||||
selectedFiles.push(..._pendingFiles);
|
||||
_pendingFiles = [];
|
||||
}
|
||||
renderHosterSummary();
|
||||
if (!uploading && selectedFiles.length > 0) buildQueuePreview();
|
||||
updateStartButton();
|
||||
updateUploadView();
|
||||
persistQueueStateSoon();
|
||||
document.getElementById('hosterModal').style.display = 'none';
|
||||
}
|
||||
|
||||
function cancelHosterModal() {
|
||||
_pendingFiles = [];
|
||||
closeHosterModal();
|
||||
}
|
||||
|
||||
@ -337,34 +346,36 @@ function setupDragDrop() {
|
||||
});
|
||||
}
|
||||
|
||||
let _pendingFiles = []; // Files waiting for hoster modal confirmation
|
||||
|
||||
function addDroppedFiles(fileList) {
|
||||
let added = 0;
|
||||
const files = Array.from(fileList);
|
||||
const newFiles = [];
|
||||
for (const file of files) {
|
||||
if (!selectedFiles.find(f => f.path === file.path)) {
|
||||
selectedFiles.push({ path: file.path, name: file.name, size: file.size });
|
||||
added++;
|
||||
if (!selectedFiles.find(f => f.path === file.path) && !_pendingFiles.find(f => f.path === file.path)) {
|
||||
newFiles.push({ path: file.path, name: file.name, size: file.size });
|
||||
}
|
||||
}
|
||||
updateUploadView();
|
||||
persistQueueStateSoon();
|
||||
if (added > 0) openHosterModal();
|
||||
if (newFiles.length > 0) {
|
||||
_pendingFiles.push(...newFiles);
|
||||
openHosterModal();
|
||||
}
|
||||
}
|
||||
|
||||
async function pickFiles() {
|
||||
const paths = await window.api.selectFiles();
|
||||
if (!paths) return;
|
||||
let added = 0;
|
||||
const newFiles = [];
|
||||
for (const p of paths) {
|
||||
if (!selectedFiles.find(f => f.path === p)) {
|
||||
if (!selectedFiles.find(f => f.path === p) && !_pendingFiles.find(f => f.path === p)) {
|
||||
const name = p.split('\\').pop().split('/').pop();
|
||||
selectedFiles.push({ path: p, name, size: null }); // size resolved by upload-manager
|
||||
added++;
|
||||
newFiles.push({ path: p, name, size: null });
|
||||
}
|
||||
}
|
||||
updateUploadView();
|
||||
persistQueueStateSoon();
|
||||
if (added > 0) openHosterModal();
|
||||
if (newFiles.length > 0) {
|
||||
_pendingFiles.push(...newFiles);
|
||||
openHosterModal();
|
||||
}
|
||||
}
|
||||
|
||||
function updateUploadView() {
|
||||
@ -675,7 +686,7 @@ document.addEventListener('click', (e) => {
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
hideContextMenu();
|
||||
closeHosterModal();
|
||||
cancelHosterModal();
|
||||
}
|
||||
});
|
||||
|
||||
@ -1517,8 +1528,8 @@ function setupListeners() {
|
||||
retrySelectedJobs();
|
||||
});
|
||||
document.getElementById('confirmHosterModalBtn').addEventListener('click', applyHosterSelection);
|
||||
document.getElementById('cancelHosterModalBtn').addEventListener('click', closeHosterModal);
|
||||
document.getElementById('closeHosterModalBtn').addEventListener('click', closeHosterModal);
|
||||
document.getElementById('cancelHosterModalBtn').addEventListener('click', cancelHosterModal);
|
||||
document.getElementById('closeHosterModalBtn').addEventListener('click', cancelHosterModal);
|
||||
document.getElementById('selectAllHostersBtn').addEventListener('click', () => {
|
||||
document.querySelectorAll('input[data-hoster-modal]').forEach(input => {
|
||||
input.checked = true;
|
||||
@ -1577,7 +1588,7 @@ function setupListeners() {
|
||||
});
|
||||
|
||||
document.getElementById('hosterModal').addEventListener('click', (e) => {
|
||||
if (e.target.id === 'hosterModal') closeHosterModal();
|
||||
if (e.target.id === 'hosterModal') cancelHosterModal();
|
||||
});
|
||||
|
||||
// Account management
|
||||
|
||||
Loading…
Reference in New Issue
Block a user