Files

50 lines
2.1 KiB
JavaScript

'use strict';
const crypto = require('node:crypto');
const SCHEME = 'mangacircus-work-v1';
const KINDS = new Set(['anilist', 'mangadex', 'weebcentral', 'hoster', 'origin']);
function normalizeWorkIdentity(value) {
if (!value || typeof value !== 'object' || value.scheme !== SCHEME
|| !KINDS.has(value.kind) || typeof value.value !== 'string'
|| !value.value.trim() || value.value.length > 300) return null;
return { scheme: SCHEME, kind: value.kind, value: value.value.trim() };
}
function resolveWorkIdentity(meta = {}, mangaId, serverId) {
const carried = normalizeWorkIdentity(meta['x-work-identity']);
if (carried) return carried;
const anilist = meta['x-anilist']?.id ?? meta['x-scraper']?.ids?.anilist;
if (anilist != null && String(anilist).trim()) return { scheme: SCHEME, kind: 'anilist', value: String(anilist).trim() };
const ids = meta['x-scraper']?.ids || {};
for (const source of ['mangadex', 'weebcentral']) {
if (ids[source] != null && String(ids[source]).trim()) {
return { scheme: SCHEME, kind: source, value: String(ids[source]).trim() };
}
}
for (const source of Object.keys(ids).sort()) {
if (!['anilist', 'mangadex', 'weebcentral'].includes(source) && !source.startsWith('peer-')
&& ids[source] != null && String(ids[source]).trim()) {
return { scheme: SCHEME, kind: 'hoster', value: `${source}:${String(ids[source]).trim()}` };
}
}
// A private, stable lineage ID lets a title safely make a round trip even if
// neither server has external metadata. It reveals neither the folder nor title.
if (typeof mangaId === 'string' && mangaId && typeof serverId === 'string' && serverId) {
const value = crypto.createHash('sha256').update(`${serverId}\0${mangaId}`).digest('hex');
return { scheme: SCHEME, kind: 'origin', value };
}
return null;
}
function sameWorkIdentity(left, right) {
const a = normalizeWorkIdentity(left), b = normalizeWorkIdentity(right);
return !!a && !!b && a.scheme === b.scheme && a.kind === b.kind && a.value === b.value;
}
module.exports = { SCHEME, normalizeWorkIdentity, resolveWorkIdentity, sameWorkIdentity };