79 lines
3.3 KiB
JavaScript
79 lines
3.3 KiB
JavaScript
'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;
|
||
};
|
||
})();
|