Add support for nip 22 tags
This commit is contained in:
@@ -33,7 +33,7 @@
|
||||
"@welshman/net": "~0.0.45",
|
||||
"@welshman/signer": "~0.0.19",
|
||||
"@welshman/store": "~0.0.15",
|
||||
"@welshman/util": "~0.0.54",
|
||||
"@welshman/util": "~0.0.58",
|
||||
"fuse.js": "^7.0.0",
|
||||
"idb": "^8.0.0",
|
||||
"svelte": "^4.2.18",
|
||||
|
||||
@@ -25,12 +25,14 @@ import {
|
||||
isLocalUrl,
|
||||
isIPAddress,
|
||||
isShareableRelayUrl,
|
||||
COMMENT,
|
||||
PROFILE,
|
||||
RELAYS,
|
||||
INBOX_RELAYS,
|
||||
FOLLOWS,
|
||||
WRAP,
|
||||
getAncestorTags,
|
||||
getReplyTags,
|
||||
getCommentTags,
|
||||
getPubkeyTagValues,
|
||||
normalizeRelayUrl,
|
||||
} from "@welshman/util"
|
||||
@@ -191,8 +193,13 @@ export class Router {
|
||||
}
|
||||
|
||||
EventAncestors = (event: TrustedEvent, type: "mentions" | "replies" | "roots") => {
|
||||
const ancestorTags =
|
||||
event.kind === COMMENT ? getCommentTags(event.tags) : getReplyTags(event.tags)
|
||||
|
||||
const tags: string[][] = (ancestorTags as any)[type] || []
|
||||
|
||||
return this.scenario(
|
||||
getAncestorTags(event.tags)[type].flatMap(([_, value, relay, pubkey]) => {
|
||||
tags.flatMap(([_, value, relay, pubkey]) => {
|
||||
const selections = [makeSelection(this.ForUser().getUrls(), 0.5)]
|
||||
|
||||
if (pubkey) {
|
||||
|
||||
+71
-31
@@ -1,10 +1,10 @@
|
||||
import {ctx} from "@welshman/lib"
|
||||
import {ctx, remove, nthEq} from "@welshman/lib"
|
||||
import {
|
||||
getAddress,
|
||||
isReplaceable,
|
||||
getAncestorTags,
|
||||
getReplyTags,
|
||||
getPubkeyTagValues,
|
||||
getIdAndAddress,
|
||||
isReplaceableKind,
|
||||
} from "@welshman/util"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {displayProfileByPubkey} from "./profiles.js"
|
||||
@@ -35,25 +35,14 @@ export const tagEvent = (event: TrustedEvent, mark = "") => {
|
||||
return tags
|
||||
}
|
||||
|
||||
export const tagReplyTo = (event: TrustedEvent) => {
|
||||
const $pubkey = pubkey.get()
|
||||
const tagValues = getIdAndAddress(event)
|
||||
const tags: string[][] = []
|
||||
export const tagEventPubkeys = (event: TrustedEvent) =>
|
||||
remove(pubkey.get()!, [event.pubkey, ...getPubkeyTagValues(event.tags)]).map(tagPubkey)
|
||||
|
||||
// Mention the event's author
|
||||
if (event.pubkey !== $pubkey) {
|
||||
tags.push(tagPubkey(event.pubkey))
|
||||
}
|
||||
|
||||
// Inherit p-tag mentions
|
||||
for (const pubkey of getPubkeyTagValues(event.tags)) {
|
||||
if (pubkey !== $pubkey) {
|
||||
tags.push(tagPubkey(pubkey))
|
||||
}
|
||||
}
|
||||
export const tagEventForReply = (event: TrustedEvent) => {
|
||||
const tags = tagEventPubkeys(event)
|
||||
|
||||
// Based on NIP 10 legacy tags, order is root, mentions, reply
|
||||
const {roots, replies, mentions} = getAncestorTags(event.tags)
|
||||
const {roots, replies, mentions} = getReplyTags(event.tags)
|
||||
|
||||
// Root comes first
|
||||
if (roots.length > 0) {
|
||||
@@ -66,12 +55,9 @@ export const tagReplyTo = (event: TrustedEvent) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we don't repeat any tag values
|
||||
const isRepeated = (v: string) => tagValues.includes(v) || tags.find(t => t[1] === v)
|
||||
|
||||
// Inherit mentions
|
||||
for (const t of mentions) {
|
||||
if (!isRepeated(t[1])) {
|
||||
if (!tags.some(nthEq(1, t[1]))) {
|
||||
tags.push([...t.slice(0, 3), "mention"])
|
||||
}
|
||||
}
|
||||
@@ -79,21 +65,73 @@ export const tagReplyTo = (event: TrustedEvent) => {
|
||||
// Inherit replies if they weren't already included
|
||||
if (roots.length > 0) {
|
||||
for (const t of replies) {
|
||||
if (!isRepeated(t[1])) {
|
||||
if (!tags.some(nthEq(1, t[1]))) {
|
||||
tags.push([...t.slice(0, 3), "mention"])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add a/e-tags for the event event
|
||||
for (const t of tagEvent(event, replies.length > 0 ? "reply" : "root")) {
|
||||
tags.push(t)
|
||||
// Finally, tag the event itself
|
||||
const mark = replies.length > 0 ? "reply" : "root"
|
||||
const hint = ctx.app.router.Event(event).getUrl()
|
||||
|
||||
// e-tag the event
|
||||
tags.push(["e", event.id, hint, mark, event.pubkey])
|
||||
|
||||
// a-tag the event
|
||||
if (isReplaceable(event)) {
|
||||
tags.push(["a", getAddress(event), hint, mark, event.pubkey])
|
||||
}
|
||||
|
||||
return tags
|
||||
}
|
||||
|
||||
export const tagReactionTo = (event: TrustedEvent) => {
|
||||
export const tagEventForComment = (event: TrustedEvent) => {
|
||||
const pubkeyHint = ctx.app.router.FromPubkey(event.pubkey).getUrl()
|
||||
const eventHint = ctx.app.router.Event(event).getUrl()
|
||||
const address = getAddress(event)
|
||||
const tags = tagEventPubkeys(event)
|
||||
const seenRoots = new Set<string>()
|
||||
|
||||
for (const [raw, ...tag] of event.tags) {
|
||||
const T = raw.toUpperCase()
|
||||
const t = raw.toLowerCase()
|
||||
|
||||
if (!["k", "e", "a", "i", "p"].includes(t)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (seenRoots.has(T)) {
|
||||
tags.push([t, ...tag])
|
||||
} else {
|
||||
tags.push([T, ...tag])
|
||||
seenRoots.add(T)
|
||||
}
|
||||
}
|
||||
|
||||
if (seenRoots.size === 0) {
|
||||
tags.push(["K", String(event.kind)])
|
||||
tags.push(["P", event.pubkey, pubkeyHint])
|
||||
tags.push(["E", event.id, eventHint, event.pubkey])
|
||||
|
||||
if (isReplaceableKind(event.kind)) {
|
||||
tags.push(["A", address, eventHint, event.pubkey])
|
||||
}
|
||||
}
|
||||
|
||||
tags.push(["k", String(event.kind)])
|
||||
tags.push(["p", event.pubkey, pubkeyHint])
|
||||
tags.push(["e", event.id, eventHint, event.pubkey])
|
||||
|
||||
if (isReplaceableKind(event.kind)) {
|
||||
tags.push(["a", address, eventHint, event.pubkey])
|
||||
}
|
||||
|
||||
return tags
|
||||
}
|
||||
|
||||
export const tagEventForReaction = (event: TrustedEvent) => {
|
||||
const hint = ctx.app.router.Event(event).getUrl()
|
||||
const tags: string[][] = []
|
||||
|
||||
// Mention the event's author
|
||||
@@ -101,9 +139,11 @@ export const tagReactionTo = (event: TrustedEvent) => {
|
||||
tags.push(tagPubkey(event.pubkey))
|
||||
}
|
||||
|
||||
// Add a/e-tags for the event
|
||||
for (const t of tagEvent(event, "root")) {
|
||||
tags.push(t)
|
||||
tags.push(["k", String(event.kind)])
|
||||
tags.push(["e", event.id, hint])
|
||||
|
||||
if (isReplaceable(event)) {
|
||||
tags.push(["a", getAddress(event), hint])
|
||||
}
|
||||
|
||||
return tags
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"@noble/hashes": "^1.6.1",
|
||||
"@welshman/lib": "~0.0.37",
|
||||
"@welshman/net": "~0.0.45",
|
||||
"@welshman/util": "~0.0.54",
|
||||
"@welshman/util": "~0.0.58",
|
||||
"nostr-tools": "^2.7.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@welshman/lib": "~0.0.37",
|
||||
"@welshman/util": "~0.0.54"
|
||||
"@welshman/util": "~0.0.58"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@welshman/lib": "~0.0.37",
|
||||
"@welshman/util": "~0.0.54",
|
||||
"@welshman/util": "~0.0.58",
|
||||
"isomorphic-ws": "^5.0.0",
|
||||
"ws": "^8.16.0"
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"@noble/hashes": "^1.6.1",
|
||||
"@welshman/lib": "~0.0.37",
|
||||
"@welshman/net": "~0.0.45",
|
||||
"@welshman/util": "~0.0.54",
|
||||
"@welshman/util": "~0.0.58",
|
||||
"nostr-tools": "^2.7.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@welshman/lib": "~0.0.37",
|
||||
"@welshman/util": "~0.0.54",
|
||||
"@welshman/util": "~0.0.58",
|
||||
"svelte": "^4.2.18"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import {verifiedSymbol, getEventHash, verifyEvent} from "nostr-tools/pure"
|
||||
import {cached, pick, now} from "@welshman/lib"
|
||||
import {getAncestorTagValues} from "./Tags.js"
|
||||
import {getAddress} from "./Address.js"
|
||||
import {cached, mapVals, first, pick, now} from "@welshman/lib"
|
||||
import {getReplyTagValues, getCommentTagValues} from "./Tags.js"
|
||||
import {getAddress, Address} from "./Address.js"
|
||||
import {
|
||||
COMMENT,
|
||||
isEphemeralKind,
|
||||
isReplaceableKind,
|
||||
isPlainReplaceableKind,
|
||||
@@ -135,9 +136,41 @@ export const isPlainReplaceable = (e: EventTemplate) => isPlainReplaceableKind(e
|
||||
export const isParameterizedReplaceable = (e: EventTemplate) =>
|
||||
isParameterizedReplaceableKind(e.kind)
|
||||
|
||||
export const isChildOf = (child: EventContent, parent: HashedEvent) => {
|
||||
const {roots, replies} = getAncestorTagValues(child.tags)
|
||||
const parentIds = replies.length > 0 ? replies : roots
|
||||
export const getAncestors = ({kind, tags}: EventTemplate) =>
|
||||
kind === COMMENT ? getCommentTagValues(tags) : getReplyTagValues(tags)
|
||||
|
||||
return getIdAndAddress(parent).some(x => parentIds.includes(x))
|
||||
export const getParentIdsAndAddrs = (event: EventTemplate) => {
|
||||
const {roots, replies} = getAncestors(event)
|
||||
|
||||
return replies.length > 0 ? replies : roots
|
||||
}
|
||||
|
||||
export const getParentIdOrAddr = (event: EventTemplate) => first(getParentIdsAndAddrs(event))
|
||||
|
||||
export const getParentIds = (event: EventTemplate) => {
|
||||
const {roots, replies} = mapVals(
|
||||
ids => ids.filter(id => !Address.isAddress(id)),
|
||||
getAncestors(event),
|
||||
)
|
||||
|
||||
return replies.length > 0 ? replies : roots
|
||||
}
|
||||
|
||||
export const getParentId = (event: EventTemplate) => first(getParentIds(event))
|
||||
|
||||
export const getParentAddrs = (event: EventTemplate) => {
|
||||
const {roots, replies} = mapVals(
|
||||
ids => ids.filter(id => Address.isAddress(id)),
|
||||
getAncestors(event),
|
||||
)
|
||||
|
||||
return replies.length > 0 ? replies : roots
|
||||
}
|
||||
|
||||
export const getParentAddr = (event: EventTemplate) => first(getParentAddrs(event))
|
||||
|
||||
export const isChildOf = (child: EventTemplate, parent: HashedEvent) => {
|
||||
const idsAndAddrs = getParentIdsAndAddrs(child)
|
||||
|
||||
return getIdAndAddress(parent).some(x => idsAndAddrs.includes(x))
|
||||
}
|
||||
|
||||
@@ -54,7 +54,17 @@ export const getKindTags = (tags: string[][]) =>
|
||||
|
||||
export const getKindTagValues = (tags: string[][]) => getKindTags(tags).map(t => parseInt(t[1]))
|
||||
|
||||
export const getAncestorTags = (tags: string[][]) => {
|
||||
export const getCommentTags = (tags: string[][]) => {
|
||||
const roots = tags.filter(t => ["A", "E", "P", "K"].includes(t[0]))
|
||||
const replies = tags.filter(t => ["a", "e", "p", "k"].includes(t[0]))
|
||||
|
||||
return {roots, replies}
|
||||
}
|
||||
|
||||
export const getCommentTagValues = (tags: string[][]) =>
|
||||
mapVals(tags => tags.map(nth(1)), getCommentTags(tags))
|
||||
|
||||
export const getReplyTags = (tags: string[][]) => {
|
||||
const validTags = tags.filter(t => ["a", "e", "q"].includes(t[0]))
|
||||
const mentionTags = validTags.filter(nthEq(0, "q"))
|
||||
const roots: string[][] = []
|
||||
@@ -90,8 +100,8 @@ export const getAncestorTags = (tags: string[][]) => {
|
||||
return {roots, replies, mentions}
|
||||
}
|
||||
|
||||
export const getAncestorTagValues = (tags: string[][]) =>
|
||||
mapVals(tags => tags.map(nth(1)), getAncestorTags(tags))
|
||||
export const getReplyTagValues = (tags: string[][]) =>
|
||||
mapVals(tags => tags.map(nth(1)), getReplyTags(tags))
|
||||
|
||||
export const uniqTags = (tags: string[][]) => uniqBy(t => t.join(":"), tags)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user