nostr-tools
Version:
Tools for making a Nostr client.
161 lines (159 loc) • 4.76 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// nip22.ts
var nip22_exports = {};
__export(nip22_exports, {
parse: () => parse
});
module.exports = __toCommonJS(nip22_exports);
var HEX64 = /^[0-9a-fA-F]{64}$/;
function parseKind(kind) {
if (!kind)
return void 0;
return /^\d+$/.test(kind) ? parseInt(kind, 10) : kind;
}
function parseAddressPointer(value, relayUrl) {
const idx = value.indexOf(":");
const idx2 = value.indexOf(":", idx + 1);
if (idx === -1 || idx2 === -1)
return void 0;
const kind = parseInt(value.slice(0, idx), 10);
if (Number.isNaN(kind))
return void 0;
const pubkey = value.slice(idx + 1, idx2);
if (!HEX64.test(pubkey))
return void 0;
return {
kind,
pubkey,
identifier: value.slice(idx2 + 1),
relays: relayUrl ? [relayUrl] : []
};
}
function parsePointer(tag) {
switch (tag[0]) {
case "E":
case "e":
if (!tag[1] || !HEX64.test(tag[1]))
return void 0;
return {
id: tag[1],
relays: tag[2] ? [tag[2]] : [],
author: tag[3] && HEX64.test(tag[3]) ? tag[3] : void 0
};
case "A":
case "a":
if (!tag[1])
return void 0;
return parseAddressPointer(tag[1], tag[2]);
case "I":
case "i":
if (!tag[1])
return void 0;
return {
value: tag[1],
hint: tag[2]
};
}
}
function parseQuote(tag) {
if (!tag[1])
return void 0;
if (tag[1].includes(":")) {
return parseAddressPointer(tag[1], tag[2]);
}
if (!HEX64.test(tag[1]))
return void 0;
return {
id: tag[1],
relays: tag[2] ? [tag[2]] : [],
author: tag[3] && HEX64.test(tag[3]) ? tag[3] : void 0
};
}
function choosePointer(candidates) {
return candidates.findLast((candidate) => candidate.tagName === "A" || candidate.tagName === "a")?.pointer || candidates.findLast((candidate) => candidate.tagName === "I" || candidate.tagName === "i")?.pointer || candidates.findLast((candidate) => candidate.tagName === "E" || candidate.tagName === "e")?.pointer;
}
function inheritRelayHints(pointer, profiles) {
if (!pointer || !("id" in pointer) || !pointer.author)
return;
const author = profiles.find((profile) => profile.pubkey === pointer.author);
if (!author || !author.relays)
return;
if (!pointer.relays) {
pointer.relays = [];
}
author.relays.forEach((url) => {
if (pointer.relays.indexOf(url) === -1)
pointer.relays.push(url);
});
author.relays = pointer.relays;
}
function parse(event) {
const result = {
root: void 0,
rootKind: void 0,
reply: void 0,
replyKind: void 0,
mentions: [],
quotes: [],
profiles: []
};
const rootCandidates = [];
const replyCandidates = [];
for (const tag of event.tags) {
if ((tag[0] === "E" || tag[0] === "A" || tag[0] === "I") && tag[1]) {
const pointer = parsePointer(tag);
if (pointer)
rootCandidates.push({ tagName: tag[0], pointer });
continue;
}
if ((tag[0] === "e" || tag[0] === "a" || tag[0] === "i") && tag[1]) {
const pointer = parsePointer(tag);
if (pointer)
replyCandidates.push({ tagName: tag[0], pointer });
continue;
}
if (tag[0] === "K") {
result.rootKind = parseKind(tag[1]);
continue;
}
if (tag[0] === "k") {
result.replyKind = parseKind(tag[1]);
continue;
}
if (tag[0] === "q") {
const pointer = parseQuote(tag);
if (pointer)
result.quotes.push(pointer);
continue;
}
if ((tag[0] === "P" || tag[0] === "p") && tag[1] && HEX64.test(tag[1])) {
result.profiles.push({
pubkey: tag[1],
relays: tag[2] ? [tag[2]] : []
});
}
}
result.root = choosePointer(rootCandidates);
result.reply = choosePointer(replyCandidates);
inheritRelayHints(result.root, result.profiles);
inheritRelayHints(result.reply, result.profiles);
result.quotes.forEach((pointer) => inheritRelayHints(pointer, result.profiles));
return result;
}