Expose Greatest source links and safe scraper inspection
This commit is contained in:
1 parent
f493afcc18
commit
d0275223a7
7 files changed
+238
-6
No files matched your search
@@ -16,6 +16,7 @@ const { scanLibrary, scanChangedLibrary, libraryStamps, snapshotIndex, restoreIn
|
||||
const { Catalog, CatalogError, collectionViews, TYPES, ROLES } = require('./catalog');
|
||||
const { RATINGS: GREATEST_RATINGS, loadCatalog: loadGreatestCatalog, findOwned: findGreatestOwned,
|
||||
countsFor: greatestCounts, scoreFor: greatestScore } = require('./greatest');
|
||||
const { hosterLinks } = require('./greatest/hosters');
|
||||
const { secret } = require('./runtime/config');
|
||||
const {
|
||||
applyPulse, applyVisit, chapterInsight, eligiblePages, emptyRecord, libraryInsight, mangaInsight, publicSummary,
|
||||
@@ -204,6 +205,28 @@ async function scraperRequest(endpoint, body) {
|
||||
return data;
|
||||
}
|
||||
|
||||
const mangaDexSearchCache = new Map();
|
||||
let lastMangaDexSearch = 0;
|
||||
async function searchGreatestMangaDex(entry) {
|
||||
const cached = mangaDexSearchCache.get(entry.id);
|
||||
if (cached && Date.now() - cached.time < 60 * 60 * 1000) return cached.results;
|
||||
if (Date.now() - lastMangaDexSearch < 2000) bad(429, 'Wait two seconds before another MangaDex lookup');
|
||||
lastMangaDexSearch = Date.now();
|
||||
let response;
|
||||
try {
|
||||
response = await fetch(`https://api.mangadex.org/manga?title=${encodeURIComponent(entry.title)}&limit=10`,
|
||||
{ headers: { accept: 'application/json' }, signal: AbortSignal.timeout(7000) });
|
||||
} catch (error) { throw new HttpError(503, `MangaDex lookup unavailable: ${error.message}`); }
|
||||
if (!response.ok) throw new HttpError(response.status === 429 ? 503 : 502, `MangaDex lookup returned HTTP ${response.status}`);
|
||||
const body = await response.json();
|
||||
const results = (body.data || []).filter(row => /^[0-9a-f-]{36}$/i.test(row.id)).map(row => ({
|
||||
title: row.attributes?.title?.en || Object.values(row.attributes?.title || {})[0] || 'Untitled',
|
||||
year: row.attributes?.year || null, url: `https://mangadex.org/title/${row.id}`,
|
||||
}));
|
||||
mangaDexSearchCache.set(entry.id, { time: Date.now(), results });
|
||||
return results;
|
||||
}
|
||||
|
||||
// Versions sorted by the sum of all user votes; ties go to the higher "priority" in chapter.json, then folder order.
|
||||
function ranked(m, ch) {
|
||||
const votes = (db.votes[m.id] && db.votes[m.id][ch.id]) || {};
|
||||
@@ -380,6 +403,7 @@ const routes = {
|
||||
chapters: owned ? owned.chapters.length : entry.chapters,
|
||||
status: owned?.meta?.status || entry.status,
|
||||
library: owned ? { id: owned.id, chapters: owned.chapters.length } : null,
|
||||
hosters: hosterLinks(entry, owned).links,
|
||||
myRating: db.greatestRatings?.[u.name]?.[entry.id] || null,
|
||||
votes: counts, score: greatestScore(counts),
|
||||
};
|
||||
@@ -397,6 +421,24 @@ const routes = {
|
||||
const votes = greatestCounts(id, all, db.users);
|
||||
return { id, myRating: rating, votes, score: greatestScore(votes) };
|
||||
},
|
||||
'GET /api/greatest/sources': async ({ u, q }) => {
|
||||
admin(u);
|
||||
const entry = greatestById.get(String(q.get('id') || ''));
|
||||
if (!entry) bad(404, 'Catalog entry not found');
|
||||
const owned = findGreatestOwned(entry, lib.mangas);
|
||||
try {
|
||||
const state = await scraperRequest('/api/state');
|
||||
return { available: true, ...hosterLinks(entry, owned, state.queue || []) };
|
||||
} catch (error) {
|
||||
return { available: false, error: error.message, ...hosterLinks(entry, owned) };
|
||||
}
|
||||
},
|
||||
'GET /api/greatest/mangadex-search': async ({ u, q }) => {
|
||||
admin(u);
|
||||
const entry = greatestById.get(String(q.get('id') || ''));
|
||||
if (!entry) bad(404, 'Catalog entry not found');
|
||||
return { results: await searchGreatestMangaDex(entry) };
|
||||
},
|
||||
|
||||
'GET /api/manga': ({ u, q }) => {
|
||||
const m = mangaOf(q.get('m')), prog = progressOf(u, m), showStory = settingsOf(u).readingStory;
|
||||
|
||||
Reference in new issue
Block a user