Redesign admin peering settings and catalogs
This commit is contained in:
1 parent
492477f86a
commit
da40d73f02
16 files changed
+1037
-85
No files matched your search
+19
-4
@@ -39,7 +39,7 @@ function connection(store, id, needGrant = true, requireReceive = false) {
|
||||
return { peer, agent, token };
|
||||
}
|
||||
function request(store, id, endpoint, options = {}) {
|
||||
const { peer, agent, token } = connection(store, id, !options.pairing && !options.access, !!options.binary);
|
||||
const { peer, agent, token } = connection(store, id, !options.pairing && !options.access, !!options.requireReceive);
|
||||
const base = new URL(peer.url), target = new URL(endpoint, base);
|
||||
if (target.origin !== base.origin || !target.pathname.startsWith('/peer/v1/')) throw new Error('Invalid peer endpoint');
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -82,6 +82,20 @@ async function access(store, id) {
|
||||
|| !Array.isArray(result.grant?.scopes)) throw new Error('Invalid peer access status');
|
||||
return result;
|
||||
}
|
||||
async function cover(store, id, shareId) {
|
||||
if (!/^m[0-9a-f]{24}$/.test(shareId)) throw new Error('Invalid peer manga ID');
|
||||
const res = await request(store, id, `/peer/v1/covers/${shareId}`, { binary: true });
|
||||
if (res.statusCode !== 200) {
|
||||
const body = await readResponse(res, 4096).catch(() => Buffer.alloc(0));
|
||||
let message; try { message = JSON.parse(body.toString()).error; } catch { message = 'Cover unavailable'; }
|
||||
throw remoteError(res.statusCode, message, res.headers['retry-after']);
|
||||
}
|
||||
const mime = String(res.headers['content-type'] || '').split(';')[0];
|
||||
if (!/^image\/(?:jpeg|png|webp|gif|avif|bmp)$/.test(mime)) throw new Error('Peer returned an unsupported cover type');
|
||||
const buffer = await readResponse(res, 5 * 1024 * 1024);
|
||||
if (!buffer.length) throw new Error('Peer returned an empty cover');
|
||||
return { buffer, mime, etag: res.headers.etag || null };
|
||||
}
|
||||
async function catalog(store, id) {
|
||||
const items = []; let cursor = null;
|
||||
for (let page = 0; page < 100; page++) {
|
||||
@@ -99,7 +113,7 @@ async function manga(store, id, shareId) {
|
||||
const result = await jsonRequest(store, id, `/peer/v1/manga/${shareId}${cursor ? `?cursor=${encodeURIComponent(cursor)}` : ''}`);
|
||||
if (result.id !== shareId || !Array.isArray(result.chapters) || result.chapters.length > 100) throw new Error('Invalid peer manga manifest');
|
||||
first ||= result; chapters.push(...result.chapters); cursor = result.nextCursor;
|
||||
if (!cursor) return { id: shareId, title: first.title, direction: first.direction, chapters };
|
||||
if (!cursor) return { id: shareId, title: first.title, ...first, chapters };
|
||||
}
|
||||
throw new Error('Peer manga exceeds chapter limit');
|
||||
}
|
||||
@@ -123,7 +137,8 @@ async function downloadPage(store, id, page, file, shouldStop) {
|
||||
if (stat && stat.size > page.bytes) { await fsp.rm(file, { force: true }); stat = null; }
|
||||
const start = stat?.size || 0;
|
||||
if (shouldStop?.()) throw new Error('Peer transfer paused');
|
||||
const res = await request(store, id, `/peer/v1/blobs/${page.id}`, { binary: true, headers: start ? { range: `bytes=${start}-`, ...(page.etag ? { 'if-match': page.etag } : {}) } : {} });
|
||||
const res = await request(store, id, `/peer/v1/blobs/${page.id}`, { binary: true, requireReceive: true,
|
||||
headers: start ? { range: `bytes=${start}-`, ...(page.etag ? { 'if-match': page.etag } : {}) } : {} });
|
||||
if (res.statusCode !== (start ? 206 : 200)) {
|
||||
const body = await readResponse(res, 4096).catch(() => Buffer.alloc(0));
|
||||
let message; try { message = JSON.parse(body.toString()).error; } catch { message = 'Transfer failed'; }
|
||||
@@ -143,4 +158,4 @@ async function downloadPage(store, id, page, file, shouldStop) {
|
||||
return { reused: false };
|
||||
}
|
||||
|
||||
module.exports = { connection, jsonRequest, probe, access, catalog, manga, chapter, downloadPage };
|
||||
module.exports = { connection, jsonRequest, probe, access, catalog, manga, cover, chapter, downloadPage };
|
||||
Reference in new issue
Block a user