50 lines
2.1 KiB
JavaScript
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 };
|