create daemon
This commit is contained in:
495
thrower_daemon/node_modules/nostr-tools/lib/cjs/nip29.js
generated
vendored
Normal file
495
thrower_daemon/node_modules/nostr-tools/lib/cjs/nip29.js
generated
vendored
Normal file
@@ -0,0 +1,495 @@
|
||||
"use strict";
|
||||
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);
|
||||
|
||||
// nip29.ts
|
||||
var nip29_exports = {};
|
||||
__export(nip29_exports, {
|
||||
GroupAdminPermission: () => GroupAdminPermission,
|
||||
encodeGroupReference: () => encodeGroupReference,
|
||||
fetchGroupAdminsEvent: () => fetchGroupAdminsEvent,
|
||||
fetchGroupMembersEvent: () => fetchGroupMembersEvent,
|
||||
fetchGroupMetadataEvent: () => fetchGroupMetadataEvent,
|
||||
fetchRelayInformationByGroupReference: () => fetchRelayInformationByGroupReference,
|
||||
generateGroupAdminsEventTemplate: () => generateGroupAdminsEventTemplate,
|
||||
generateGroupMembersEventTemplate: () => generateGroupMembersEventTemplate,
|
||||
generateGroupMetadataEventTemplate: () => generateGroupMetadataEventTemplate,
|
||||
getNormalizedRelayURLByGroupReference: () => getNormalizedRelayURLByGroupReference,
|
||||
loadGroup: () => loadGroup,
|
||||
loadGroupFromCode: () => loadGroupFromCode,
|
||||
parseGroupAdminsEvent: () => parseGroupAdminsEvent,
|
||||
parseGroupCode: () => parseGroupCode,
|
||||
parseGroupMembersEvent: () => parseGroupMembersEvent,
|
||||
parseGroupMetadataEvent: () => parseGroupMetadataEvent,
|
||||
subscribeRelayGroupsMetadataEvents: () => subscribeRelayGroupsMetadataEvents,
|
||||
validateGroupAdminsEvent: () => validateGroupAdminsEvent,
|
||||
validateGroupMembersEvent: () => validateGroupMembersEvent,
|
||||
validateGroupMetadataEvent: () => validateGroupMetadataEvent
|
||||
});
|
||||
module.exports = __toCommonJS(nip29_exports);
|
||||
|
||||
// nip11.ts
|
||||
var _fetch;
|
||||
try {
|
||||
_fetch = fetch;
|
||||
} catch {
|
||||
}
|
||||
async function fetchRelayInformation(url) {
|
||||
return await (await fetch(url.replace("ws://", "http://").replace("wss://", "https://"), {
|
||||
headers: { Accept: "application/nostr+json" }
|
||||
})).json();
|
||||
}
|
||||
|
||||
// nip19.ts
|
||||
var import_utils2 = require("@noble/hashes/utils");
|
||||
var import_base = require("@scure/base");
|
||||
|
||||
// utils.ts
|
||||
var import_utils = require("@noble/hashes/utils");
|
||||
var utf8Decoder = new TextDecoder("utf-8");
|
||||
var utf8Encoder = new TextEncoder();
|
||||
function normalizeURL(url) {
|
||||
try {
|
||||
if (url.indexOf("://") === -1)
|
||||
url = "wss://" + url;
|
||||
let p = new URL(url);
|
||||
p.pathname = p.pathname.replace(/\/+/g, "/");
|
||||
if (p.pathname.endsWith("/"))
|
||||
p.pathname = p.pathname.slice(0, -1);
|
||||
if (p.port === "80" && p.protocol === "ws:" || p.port === "443" && p.protocol === "wss:")
|
||||
p.port = "";
|
||||
p.searchParams.sort();
|
||||
p.hash = "";
|
||||
return p.toString();
|
||||
} catch (e) {
|
||||
throw new Error(`Invalid URL: ${url}`);
|
||||
}
|
||||
}
|
||||
|
||||
// nip19.ts
|
||||
var NostrTypeGuard = {
|
||||
isNProfile: (value) => /^nprofile1[a-z\d]+$/.test(value || ""),
|
||||
isNEvent: (value) => /^nevent1[a-z\d]+$/.test(value || ""),
|
||||
isNAddr: (value) => /^naddr1[a-z\d]+$/.test(value || ""),
|
||||
isNSec: (value) => /^nsec1[a-z\d]{58}$/.test(value || ""),
|
||||
isNPub: (value) => /^npub1[a-z\d]{58}$/.test(value || ""),
|
||||
isNote: (value) => /^note1[a-z\d]+$/.test(value || ""),
|
||||
isNcryptsec: (value) => /^ncryptsec1[a-z\d]+$/.test(value || "")
|
||||
};
|
||||
var Bech32MaxSize = 5e3;
|
||||
function decode(code) {
|
||||
let { prefix, words } = import_base.bech32.decode(code, Bech32MaxSize);
|
||||
let data = new Uint8Array(import_base.bech32.fromWords(words));
|
||||
switch (prefix) {
|
||||
case "nprofile": {
|
||||
let tlv = parseTLV(data);
|
||||
if (!tlv[0]?.[0])
|
||||
throw new Error("missing TLV 0 for nprofile");
|
||||
if (tlv[0][0].length !== 32)
|
||||
throw new Error("TLV 0 should be 32 bytes");
|
||||
return {
|
||||
type: "nprofile",
|
||||
data: {
|
||||
pubkey: (0, import_utils2.bytesToHex)(tlv[0][0]),
|
||||
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []
|
||||
}
|
||||
};
|
||||
}
|
||||
case "nevent": {
|
||||
let tlv = parseTLV(data);
|
||||
if (!tlv[0]?.[0])
|
||||
throw new Error("missing TLV 0 for nevent");
|
||||
if (tlv[0][0].length !== 32)
|
||||
throw new Error("TLV 0 should be 32 bytes");
|
||||
if (tlv[2] && tlv[2][0].length !== 32)
|
||||
throw new Error("TLV 2 should be 32 bytes");
|
||||
if (tlv[3] && tlv[3][0].length !== 4)
|
||||
throw new Error("TLV 3 should be 4 bytes");
|
||||
return {
|
||||
type: "nevent",
|
||||
data: {
|
||||
id: (0, import_utils2.bytesToHex)(tlv[0][0]),
|
||||
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : [],
|
||||
author: tlv[2]?.[0] ? (0, import_utils2.bytesToHex)(tlv[2][0]) : void 0,
|
||||
kind: tlv[3]?.[0] ? parseInt((0, import_utils2.bytesToHex)(tlv[3][0]), 16) : void 0
|
||||
}
|
||||
};
|
||||
}
|
||||
case "naddr": {
|
||||
let tlv = parseTLV(data);
|
||||
if (!tlv[0]?.[0])
|
||||
throw new Error("missing TLV 0 for naddr");
|
||||
if (!tlv[2]?.[0])
|
||||
throw new Error("missing TLV 2 for naddr");
|
||||
if (tlv[2][0].length !== 32)
|
||||
throw new Error("TLV 2 should be 32 bytes");
|
||||
if (!tlv[3]?.[0])
|
||||
throw new Error("missing TLV 3 for naddr");
|
||||
if (tlv[3][0].length !== 4)
|
||||
throw new Error("TLV 3 should be 4 bytes");
|
||||
return {
|
||||
type: "naddr",
|
||||
data: {
|
||||
identifier: utf8Decoder.decode(tlv[0][0]),
|
||||
pubkey: (0, import_utils2.bytesToHex)(tlv[2][0]),
|
||||
kind: parseInt((0, import_utils2.bytesToHex)(tlv[3][0]), 16),
|
||||
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []
|
||||
}
|
||||
};
|
||||
}
|
||||
case "nsec":
|
||||
return { type: prefix, data };
|
||||
case "npub":
|
||||
case "note":
|
||||
return { type: prefix, data: (0, import_utils2.bytesToHex)(data) };
|
||||
default:
|
||||
throw new Error(`unknown prefix ${prefix}`);
|
||||
}
|
||||
}
|
||||
function parseTLV(data) {
|
||||
let result = {};
|
||||
let rest = data;
|
||||
while (rest.length > 0) {
|
||||
let t = rest[0];
|
||||
let l = rest[1];
|
||||
let v = rest.slice(2, 2 + l);
|
||||
rest = rest.slice(2 + l);
|
||||
if (v.length < l)
|
||||
throw new Error(`not enough data to read on TLV ${t}`);
|
||||
result[t] = result[t] || [];
|
||||
result[t].push(v);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// nip29.ts
|
||||
var GroupAdminPermission = /* @__PURE__ */ ((GroupAdminPermission2) => {
|
||||
GroupAdminPermission2["AddUser"] = "add-user";
|
||||
GroupAdminPermission2["EditMetadata"] = "edit-metadata";
|
||||
GroupAdminPermission2["DeleteEvent"] = "delete-event";
|
||||
GroupAdminPermission2["RemoveUser"] = "remove-user";
|
||||
GroupAdminPermission2["AddPermission"] = "add-permission";
|
||||
GroupAdminPermission2["RemovePermission"] = "remove-permission";
|
||||
GroupAdminPermission2["EditGroupStatus"] = "edit-group-status";
|
||||
GroupAdminPermission2["PutUser"] = "put-user";
|
||||
GroupAdminPermission2["CreateGroup"] = "create-group";
|
||||
GroupAdminPermission2["DeleteGroup"] = "delete-group";
|
||||
GroupAdminPermission2["CreateInvite"] = "create-invite";
|
||||
return GroupAdminPermission2;
|
||||
})(GroupAdminPermission || {});
|
||||
function generateGroupMetadataEventTemplate(group) {
|
||||
const tags = [["d", group.metadata.id]];
|
||||
group.metadata.name && tags.push(["name", group.metadata.name]);
|
||||
group.metadata.picture && tags.push(["picture", group.metadata.picture]);
|
||||
group.metadata.about && tags.push(["about", group.metadata.about]);
|
||||
group.metadata.isPublic && tags.push(["public"]);
|
||||
group.metadata.isOpen && tags.push(["open"]);
|
||||
return {
|
||||
content: "",
|
||||
created_at: Math.floor(Date.now() / 1e3),
|
||||
kind: 39e3,
|
||||
tags
|
||||
};
|
||||
}
|
||||
function validateGroupMetadataEvent(event) {
|
||||
if (event.kind !== 39e3)
|
||||
return false;
|
||||
if (!event.pubkey)
|
||||
return false;
|
||||
const requiredTags = ["d"];
|
||||
for (const tag of requiredTags) {
|
||||
if (!event.tags.find(([t]) => t == tag))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function generateGroupAdminsEventTemplate(group, admins) {
|
||||
const tags = [["d", group.metadata.id]];
|
||||
for (const admin of admins) {
|
||||
tags.push(["p", admin.pubkey, admin.label || "", ...admin.permissions]);
|
||||
}
|
||||
return {
|
||||
content: "",
|
||||
created_at: Math.floor(Date.now() / 1e3),
|
||||
kind: 39001,
|
||||
tags
|
||||
};
|
||||
}
|
||||
function validateGroupAdminsEvent(event) {
|
||||
if (event.kind !== 39001)
|
||||
return false;
|
||||
const requiredTags = ["d"];
|
||||
for (const tag of requiredTags) {
|
||||
if (!event.tags.find(([t]) => t == tag))
|
||||
return false;
|
||||
}
|
||||
for (const [tag, _value, _label, ...permissions] of event.tags) {
|
||||
if (tag !== "p")
|
||||
continue;
|
||||
for (let i = 0; i < permissions.length; i += 1) {
|
||||
if (typeof permissions[i] !== "string")
|
||||
return false;
|
||||
if (!Object.values(GroupAdminPermission).includes(permissions[i]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function generateGroupMembersEventTemplate(group, members) {
|
||||
const tags = [["d", group.metadata.id]];
|
||||
for (const member of members) {
|
||||
tags.push(["p", member.pubkey, member.label || ""]);
|
||||
}
|
||||
return {
|
||||
content: "",
|
||||
created_at: Math.floor(Date.now() / 1e3),
|
||||
kind: 39002,
|
||||
tags
|
||||
};
|
||||
}
|
||||
function validateGroupMembersEvent(event) {
|
||||
if (event.kind !== 39002)
|
||||
return false;
|
||||
const requiredTags = ["d"];
|
||||
for (const tag of requiredTags) {
|
||||
if (!event.tags.find(([t]) => t == tag))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function getNormalizedRelayURLByGroupReference(groupReference) {
|
||||
return normalizeURL(groupReference.host);
|
||||
}
|
||||
async function fetchRelayInformationByGroupReference(groupReference) {
|
||||
const normalizedRelayURL = getNormalizedRelayURLByGroupReference(groupReference);
|
||||
return fetchRelayInformation(normalizedRelayURL);
|
||||
}
|
||||
async function fetchGroupMetadataEvent({
|
||||
pool,
|
||||
groupReference,
|
||||
relayInformation,
|
||||
normalizedRelayURL
|
||||
}) {
|
||||
if (!normalizedRelayURL) {
|
||||
normalizedRelayURL = getNormalizedRelayURLByGroupReference(groupReference);
|
||||
}
|
||||
if (!relayInformation) {
|
||||
relayInformation = await fetchRelayInformation(normalizedRelayURL);
|
||||
}
|
||||
const groupMetadataEvent = await pool.get([normalizedRelayURL], {
|
||||
kinds: [39e3],
|
||||
authors: [relayInformation.pubkey],
|
||||
"#d": [groupReference.id]
|
||||
});
|
||||
if (!groupMetadataEvent)
|
||||
throw new Error(`group '${groupReference.id}' not found on ${normalizedRelayURL}`);
|
||||
return groupMetadataEvent;
|
||||
}
|
||||
function parseGroupMetadataEvent(event) {
|
||||
if (!validateGroupMetadataEvent(event))
|
||||
throw new Error("invalid group metadata event");
|
||||
const metadata = {
|
||||
id: "",
|
||||
pubkey: event.pubkey
|
||||
};
|
||||
for (const [tag, value] of event.tags) {
|
||||
switch (tag) {
|
||||
case "d":
|
||||
metadata.id = value;
|
||||
break;
|
||||
case "name":
|
||||
metadata.name = value;
|
||||
break;
|
||||
case "picture":
|
||||
metadata.picture = value;
|
||||
break;
|
||||
case "about":
|
||||
metadata.about = value;
|
||||
break;
|
||||
case "public":
|
||||
metadata.isPublic = true;
|
||||
break;
|
||||
case "open":
|
||||
metadata.isOpen = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
async function fetchGroupAdminsEvent({
|
||||
pool,
|
||||
groupReference,
|
||||
relayInformation,
|
||||
normalizedRelayURL
|
||||
}) {
|
||||
if (!normalizedRelayURL) {
|
||||
normalizedRelayURL = getNormalizedRelayURLByGroupReference(groupReference);
|
||||
}
|
||||
if (!relayInformation) {
|
||||
relayInformation = await fetchRelayInformation(normalizedRelayURL);
|
||||
}
|
||||
const groupAdminsEvent = await pool.get([normalizedRelayURL], {
|
||||
kinds: [39001],
|
||||
authors: [relayInformation.pubkey],
|
||||
"#d": [groupReference.id]
|
||||
});
|
||||
if (!groupAdminsEvent)
|
||||
throw new Error(`admins for group '${groupReference.id}' not found on ${normalizedRelayURL}`);
|
||||
return groupAdminsEvent;
|
||||
}
|
||||
function parseGroupAdminsEvent(event) {
|
||||
if (!validateGroupAdminsEvent(event))
|
||||
throw new Error("invalid group admins event");
|
||||
const admins = [];
|
||||
for (const [tag, value, label, ...permissions] of event.tags) {
|
||||
if (tag !== "p")
|
||||
continue;
|
||||
admins.push({
|
||||
pubkey: value,
|
||||
label,
|
||||
permissions
|
||||
});
|
||||
}
|
||||
return admins;
|
||||
}
|
||||
async function fetchGroupMembersEvent({
|
||||
pool,
|
||||
groupReference,
|
||||
relayInformation,
|
||||
normalizedRelayURL
|
||||
}) {
|
||||
if (!normalizedRelayURL) {
|
||||
normalizedRelayURL = getNormalizedRelayURLByGroupReference(groupReference);
|
||||
}
|
||||
if (!relayInformation) {
|
||||
relayInformation = await fetchRelayInformation(normalizedRelayURL);
|
||||
}
|
||||
const groupMembersEvent = await pool.get([normalizedRelayURL], {
|
||||
kinds: [39002],
|
||||
authors: [relayInformation.pubkey],
|
||||
"#d": [groupReference.id]
|
||||
});
|
||||
if (!groupMembersEvent)
|
||||
throw new Error(`members for group '${groupReference.id}' not found on ${normalizedRelayURL}`);
|
||||
return groupMembersEvent;
|
||||
}
|
||||
function parseGroupMembersEvent(event) {
|
||||
if (!validateGroupMembersEvent(event))
|
||||
throw new Error("invalid group members event");
|
||||
const members = [];
|
||||
for (const [tag, value, label] of event.tags) {
|
||||
if (tag !== "p")
|
||||
continue;
|
||||
members.push({
|
||||
pubkey: value,
|
||||
label
|
||||
});
|
||||
}
|
||||
return members;
|
||||
}
|
||||
async function loadGroup({
|
||||
pool,
|
||||
groupReference,
|
||||
normalizedRelayURL,
|
||||
relayInformation
|
||||
}) {
|
||||
if (!normalizedRelayURL) {
|
||||
normalizedRelayURL = getNormalizedRelayURLByGroupReference(groupReference);
|
||||
}
|
||||
if (!relayInformation) {
|
||||
relayInformation = await fetchRelayInformation(normalizedRelayURL);
|
||||
}
|
||||
const metadataEvent = await fetchGroupMetadataEvent({ pool, groupReference, normalizedRelayURL, relayInformation });
|
||||
const metadata = parseGroupMetadataEvent(metadataEvent);
|
||||
const adminsEvent = await fetchGroupAdminsEvent({ pool, groupReference, normalizedRelayURL, relayInformation });
|
||||
const admins = parseGroupAdminsEvent(adminsEvent);
|
||||
const membersEvent = await fetchGroupMembersEvent({ pool, groupReference, normalizedRelayURL, relayInformation });
|
||||
const members = parseGroupMembersEvent(membersEvent);
|
||||
const group = {
|
||||
relay: normalizedRelayURL,
|
||||
metadata,
|
||||
admins,
|
||||
members,
|
||||
reference: groupReference
|
||||
};
|
||||
return group;
|
||||
}
|
||||
async function loadGroupFromCode(pool, code) {
|
||||
const groupReference = parseGroupCode(code);
|
||||
if (!groupReference)
|
||||
throw new Error("invalid group code");
|
||||
return loadGroup({ pool, groupReference });
|
||||
}
|
||||
function parseGroupCode(code) {
|
||||
if (NostrTypeGuard.isNAddr(code)) {
|
||||
try {
|
||||
let { data } = decode(code);
|
||||
let { relays, identifier } = data;
|
||||
if (!relays || relays.length === 0)
|
||||
return null;
|
||||
let host = relays[0];
|
||||
if (host.startsWith("wss://")) {
|
||||
host = host.slice(6);
|
||||
}
|
||||
return { host, id: identifier };
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
} else if (code.split("'").length === 2) {
|
||||
let spl = code.split("'");
|
||||
return { host: spl[0], id: spl[1] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function encodeGroupReference(gr) {
|
||||
const { host, id } = gr;
|
||||
const normalizedHost = host.replace(/^(https?:\/\/|wss?:\/\/)/, "");
|
||||
return `${normalizedHost}'${id}`;
|
||||
}
|
||||
function subscribeRelayGroupsMetadataEvents({
|
||||
pool,
|
||||
relayURL,
|
||||
onError,
|
||||
onEvent,
|
||||
onConnect
|
||||
}) {
|
||||
let sub;
|
||||
const normalizedRelayURL = normalizeURL(relayURL);
|
||||
fetchRelayInformation(normalizedRelayURL).then(async (info) => {
|
||||
const abstractedRelay = await pool.ensureRelay(normalizedRelayURL);
|
||||
onConnect?.();
|
||||
sub = abstractedRelay.prepareSubscription(
|
||||
[
|
||||
{
|
||||
kinds: [39e3],
|
||||
limit: 50,
|
||||
authors: [info.pubkey]
|
||||
}
|
||||
],
|
||||
{
|
||||
onevent(event) {
|
||||
onEvent(event);
|
||||
}
|
||||
}
|
||||
);
|
||||
}).catch((err) => {
|
||||
sub.close();
|
||||
onError(err);
|
||||
});
|
||||
return () => sub.close();
|
||||
}
|
||||
Reference in New Issue
Block a user