Checkpoint peering identity and opt-in discovery
This commit is contained in:
1 parent
eba9b50e30
commit
47de081721
44 files changed
+1557
-55
No files matched your search
@@ -0,0 +1,49 @@
|
||||
'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 };
|
||||
Reference in new issue
Block a user