diora-web/static/js/app/57-cloud-inbox.js
mrwnslz cec07dd208
Some checks failed
Test / e2e (push) Waiting to run
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Has been cancelled
Bücher: „Eingang“ – eine Cloud-Quelle bringt ihre neuen Bücher von selbst in die Bibliothek (Gerät holt, verschlüsselt, lädt hoch; Server merkt sich, was übernommen ist); sw v147
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 18:12:39 +02:00

79 lines
3.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
// ---------------------------------------------------------------------------
// "Eingang" (docs/library.md): a cloud source marked so brings its new books into the
// library by itself. When the library loads, the server says which files of such sources
// no device has taken yet (and keeps them for this device ten minutes); each is fetched
// through the server, encrypted here like any import, uploaded, and reported done. A book
// already in the library (same title and author) is left out. The folder stays as it is.
// Only where the book key is there; not in diora Reader (e-readers: battery, weak Wi-Fi).
// ---------------------------------------------------------------------------
const CLOUD_INBOX_EVERY_MS = 5 * 60 * 1000;
let _cloudInboxBusy = false;
let _cloudInboxLast = 0;
function _cloudInboxKeyReady() {
// getOrCreateEncKey() would make a new key when there is none: never import without the real one.
try { return !!localStorage.getItem(`diora_enc_key_${window.USER_ID || 0}`); } catch (e) { return false; }
}
async function cloudInboxCheck(force) {
if (typeof IS_AUTHENTICATED === 'undefined' || !IS_AUTHENTICATED) return;
if (document.documentElement.classList.contains('nui-reader-app')) return;
if (_cloudInboxBusy || !_cloudInboxKeyReady()) return;
if (!force && Date.now() - _cloudInboxLast < CLOUD_INBOX_EVERY_MS) return;
_cloudInboxBusy = true;
_cloudInboxLast = Date.now();
const statusEl = $('book-upload-status');
const taken = [];
try {
const r = await fetch('/books/cloud/inbox/', {cache: 'no-store'});
if (!r.ok) return;
const files = (await r.json()).files || [];
for (let i = 0; i < files.length; i++) {
const f = files[i];
if (statusEl) statusEl.textContent = `Eingang „${f.label}“: ${i + 1} von ${files.length} – ${f.name} …`;
let result = 'failed';
try {
if (f.size > DIORA_CONFIG.ebookMaxBytes) {
result = 'too_big';
} else {
const res = await fetch(`/books/cloud/${f.source}/fetch/?path=${encodeURIComponent(f.path)}`);
if (res.ok) {
const out = await _importEbookBuffer(await res.arrayBuffer(), f.name, null, {reload: false, skipKnown: true});
result = out === 'dup' ? 'known' : out ? 'imported' : 'failed';
}
}
} catch (e) {
result = 'failed';
}
if (result === 'imported') taken.push(f);
await fetch(`/books/cloud/${f.source}/done/`, {
method: 'POST', headers: {'Content-Type': 'application/json'},
body: JSON.stringify({path: f.path, result}),
}).catch(() => {});
}
} catch (e) {
// Offline or the source unreachable: next time.
} finally {
_cloudInboxBusy = false;
}
if (statusEl) {
const labels = [...new Set(taken.map(f => f.label))].map(l => `„${l}“`).join(', ');
statusEl.textContent = taken.length
? `${taken.length === 1 ? 'Ein neues Buch' : taken.length + ' neue Bücher'} aus ${labels} übernommen.` : '';
}
if (taken.length) loadBookList();
}
// After the list has loaded (and the key is known), quietly look into the inboxes.
(function () {
const orig = window.loadBookList;
if (typeof orig !== 'function') return;
window.loadBookList = async function () {
const out = await orig.apply(this, arguments);
setTimeout(() => cloudInboxCheck(false), 1500);
return out;
};
})();