move to pkg
This commit is contained in:
@ -1,5 +1,4 @@
|
||||
import { NostrPrefix } from "System";
|
||||
import { parseNostrLink, tryParseNostrLink } from ".";
|
||||
import { NostrPrefix } from "@snort/system";
|
||||
import { splitByUrl, magnetURIDecode, getRelayName } from ".";
|
||||
import { describe, expect } from "@jest/globals";
|
||||
|
||||
@ -93,47 +92,3 @@ describe("getRelayName", () => {
|
||||
expect(output).toEqual("relay.example2.com?broadcast=true");
|
||||
});
|
||||
});
|
||||
|
||||
describe("tryParseNostrLink", () => {
|
||||
it("is a valid nostr link", () => {
|
||||
expect(parseNostrLink("nostr:npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg")).toMatchObject({
|
||||
id: "7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e",
|
||||
type: NostrPrefix.PublicKey,
|
||||
});
|
||||
expect(parseNostrLink("web+nostr:npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg")).toMatchObject({
|
||||
id: "7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e",
|
||||
type: NostrPrefix.PublicKey,
|
||||
});
|
||||
expect(parseNostrLink("nostr:note15449edq4qa5wzgqvh8td0q0dp6hwtes4pknsrm7eygeenhlj99xsq94wu9")).toMatchObject({
|
||||
id: "a56a5cb4150768e1200cb9d6d781ed0eaee5e6150da701efd9223399dff2294d",
|
||||
type: NostrPrefix.Note,
|
||||
});
|
||||
expect(
|
||||
parseNostrLink(
|
||||
"nostr:nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p"
|
||||
)
|
||||
).toMatchObject({
|
||||
id: "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
|
||||
type: NostrPrefix.Profile,
|
||||
relays: ["wss://r.x.com", "wss://djbas.sadkb.com"],
|
||||
});
|
||||
expect(parseNostrLink("nostr:nevent1qqs226juks2sw68pyqxtn4khs8ksath9uc2smfcpalvjyvuemlezjngrd87dq")).toMatchObject({
|
||||
id: "a56a5cb4150768e1200cb9d6d781ed0eaee5e6150da701efd9223399dff2294d",
|
||||
type: NostrPrefix.Event,
|
||||
});
|
||||
expect(
|
||||
parseNostrLink(
|
||||
"nostr:naddr1qqzkjurnw4ksz9thwden5te0wfjkccte9ehx7um5wghx7un8qgs2d90kkcq3nk2jry62dyf50k0h36rhpdtd594my40w9pkal876jxgrqsqqqa28pccpzu"
|
||||
)
|
||||
).toMatchObject({
|
||||
id: "ipsum",
|
||||
type: NostrPrefix.Address,
|
||||
relays: ["wss://relay.nostr.org"],
|
||||
author: "a695f6b60119d9521934a691347d9f78e8770b56da16bb255ee286ddf9fda919",
|
||||
kind: 30023,
|
||||
});
|
||||
});
|
||||
test.each(["nostr:npub", "web+nostr:npub", "nostr:nevent1xxx"])("should return false for invalid nostr links", lb => {
|
||||
expect(tryParseNostrLink(lb)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
@ -13,12 +13,9 @@ import {
|
||||
EventKind,
|
||||
encodeTLV,
|
||||
NostrPrefix,
|
||||
decodeTLV,
|
||||
TLVEntryType,
|
||||
NostrEvent,
|
||||
} from "System";
|
||||
import { MetadataCache } from "Cache";
|
||||
import NostrLink from "Element/NostrLink";
|
||||
MetadataCache,
|
||||
} from "@snort/system";
|
||||
|
||||
export const sha256 = (str: string | Uint8Array): u256 => {
|
||||
return utils.bytesToHex(hash(str));
|
||||
@ -506,113 +503,6 @@ export function getUrlHostname(url?: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export interface NostrLink {
|
||||
type: NostrPrefix;
|
||||
id: string;
|
||||
kind?: number;
|
||||
author?: string;
|
||||
relays?: Array<string>;
|
||||
encode(): string;
|
||||
}
|
||||
|
||||
export function validateNostrLink(link: string): boolean {
|
||||
try {
|
||||
const parsedLink = parseNostrLink(link);
|
||||
if (!parsedLink) {
|
||||
return false;
|
||||
}
|
||||
if (parsedLink.type === NostrPrefix.PublicKey || parsedLink.type === NostrPrefix.Note) {
|
||||
return parsedLink.id.length === 64;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function tryParseNostrLink(link: string, prefixHint?: NostrPrefix): NostrLink | undefined {
|
||||
try {
|
||||
return parseNostrLink(link, prefixHint);
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function parseNostrLink(link: string, prefixHint?: NostrPrefix): NostrLink {
|
||||
const entity = link.startsWith("web+nostr:") || link.startsWith("nostr:") ? link.split(":")[1] : link;
|
||||
|
||||
const isPrefix = (prefix: NostrPrefix) => {
|
||||
return entity.startsWith(prefix);
|
||||
};
|
||||
|
||||
if (isPrefix(NostrPrefix.PublicKey)) {
|
||||
const id = bech32ToHex(entity);
|
||||
if (id.length !== 64) throw new Error("Invalid nostr link, must contain 32 byte id");
|
||||
return {
|
||||
type: NostrPrefix.PublicKey,
|
||||
id: id,
|
||||
encode: () => hexToBech32(NostrPrefix.PublicKey, id),
|
||||
};
|
||||
} else if (isPrefix(NostrPrefix.Note)) {
|
||||
const id = bech32ToHex(entity);
|
||||
if (id.length !== 64) throw new Error("Invalid nostr link, must contain 32 byte id");
|
||||
return {
|
||||
type: NostrPrefix.Note,
|
||||
id: id,
|
||||
encode: () => hexToBech32(NostrPrefix.Note, id),
|
||||
};
|
||||
} else if (isPrefix(NostrPrefix.Profile) || isPrefix(NostrPrefix.Event) || isPrefix(NostrPrefix.Address)) {
|
||||
const decoded = decodeTLV(entity);
|
||||
|
||||
const id = decoded.find(a => a.type === TLVEntryType.Special)?.value as string;
|
||||
const relays = decoded.filter(a => a.type === TLVEntryType.Relay).map(a => a.value as string);
|
||||
const author = decoded.find(a => a.type === TLVEntryType.Author)?.value as string;
|
||||
const kind = decoded.find(a => a.type === TLVEntryType.Kind)?.value as number;
|
||||
|
||||
const encode = () => {
|
||||
return entity; // return original
|
||||
};
|
||||
if (isPrefix(NostrPrefix.Profile)) {
|
||||
if (id.length !== 64) throw new Error("Invalid nostr link, must contain 32 byte id");
|
||||
return {
|
||||
type: NostrPrefix.Profile,
|
||||
id,
|
||||
relays,
|
||||
kind,
|
||||
author,
|
||||
encode,
|
||||
};
|
||||
} else if (isPrefix(NostrPrefix.Event)) {
|
||||
if (id.length !== 64) throw new Error("Invalid nostr link, must contain 32 byte id");
|
||||
return {
|
||||
type: NostrPrefix.Event,
|
||||
id,
|
||||
relays,
|
||||
kind,
|
||||
author,
|
||||
encode,
|
||||
};
|
||||
} else if (isPrefix(NostrPrefix.Address)) {
|
||||
return {
|
||||
type: NostrPrefix.Address,
|
||||
id,
|
||||
relays,
|
||||
kind,
|
||||
author,
|
||||
encode,
|
||||
};
|
||||
}
|
||||
} else if (prefixHint) {
|
||||
return {
|
||||
type: prefixHint,
|
||||
id: link,
|
||||
encode: () => hexToBech32(prefixHint, link),
|
||||
};
|
||||
}
|
||||
throw new Error("Invalid nostr link");
|
||||
}
|
||||
|
||||
export function sanitizeRelayUrl(url: string) {
|
||||
try {
|
||||
return new URL(url).toString();
|
||||
|
Reference in New Issue
Block a user