Add update functions to lists, document Encryptable, fix tag inheritance

This commit is contained in:
Jon Staab
2024-10-07 14:03:12 -07:00
parent 944ee61b88
commit 2156aeaeb5
3 changed files with 67 additions and 7 deletions
+2 -2
View File
@@ -40,14 +40,14 @@ export const tagReplyTo = (event: TrustedEvent) => {
} }
// Inherit p-tag mentions // Inherit p-tag mentions
for (const pubkey of getPubkeyTagValues(tags)) { for (const pubkey of getPubkeyTagValues(event.tags)) {
if (pubkey !== $pubkey) { if (pubkey !== $pubkey) {
tags.push(tagPubkey(pubkey)) tags.push(tagPubkey(pubkey))
} }
} }
// Based on NIP 10 legacy tags, order is root, mentions, reply // Based on NIP 10 legacy tags, order is root, mentions, reply
const {roots, replies, mentions} = getAncestorTags(tags) const {roots, replies, mentions} = getAncestorTags(event.tags)
// Root comes first // Root comes first
if (roots.length > 0) { if (roots.length > 0) {
+25 -3
View File
@@ -8,6 +8,8 @@ export type EncryptableParams = {
content?: string content?: string
} }
export type EncryptableUpdates = Partial<EventContent>
export type EncryptableResult = { export type EncryptableResult = {
kind: number, kind: number,
tags: string[][] tags: string[][]
@@ -15,15 +17,35 @@ export type EncryptableResult = {
} }
export type DecryptedEvent = TrustedEvent & { export type DecryptedEvent = TrustedEvent & {
plaintext: Partial<EventContent> plaintext: EncryptableUpdates
} }
export const asDecryptedEvent = (event: TrustedEvent, plaintext: Partial<EventContent> = {}) => export const asDecryptedEvent = (event: TrustedEvent, plaintext: EncryptableUpdates = {}) =>
({...event, plaintext}) as DecryptedEvent ({...event, plaintext}) as DecryptedEvent
/**
* Represents an encryptable event with optional updates.
*/
export class Encryptable { export class Encryptable {
constructor(readonly event: EncryptableParams, readonly updates: Partial<EventContent>) {} /**
* Creates an instance of Encryptable.
* @param event - An EventTemplate with optional tags and content.
* @param updates - Plaintext updates to be applied to the event content.
* @example
* Here's an example which enables updating a private mute list:
* ```
* const event = {kind: 10000, content: "", tags: []} // An event, only kind is required
* const encryptable = new Encryptable(event, {content: JSON.stringify([["e", "bad word"]])})
* const eventTemplate = await encryptable.reconcile(myEncryptFunction)
* ```
*/
constructor(readonly event: EncryptableParams, readonly updates: EncryptableUpdates) {}
/**
* Encrypts plaintext updates and merges them into the event template.
* @param encrypt - The encryption function to be used.
* @returns A promise that resolves to the reconciled and encrypted event.
*/
async reconcile(encrypt: Encrypt): Promise<EncryptableResult> { async reconcile(encrypt: Encrypt): Promise<EncryptableResult> {
const encryptContent = () => { const encryptContent = () => {
if (!this.updates.content) return null if (!this.updates.content) return null
+40 -2
View File
@@ -1,7 +1,8 @@
import {parseJson} from "@welshman/lib" import {parseJson, append, nthNe, nthEq} from "@welshman/lib"
import {Address} from "./Address" import {Address} from "./Address"
import {isShareableRelayUrl} from "./Relay" import {isShareableRelayUrl} from "./Relay"
import {DecryptedEvent} from "./Encryptable" import {Encryptable, DecryptedEvent} from "./Encryptable"
import type {EncryptableUpdates} from "./Encryptable"
export type ListParams = { export type ListParams = {
kind: number kind: number
@@ -41,3 +42,40 @@ export const readList = (event: DecryptedEvent): PublishedList => {
export const getListTags = (list: List | undefined) => export const getListTags = (list: List | undefined) =>
[...list?.publicTags || [], ...list?.privateTags || []] [...list?.publicTags || [], ...list?.privateTags || []]
export const removeFromList = (list: List, value: string) => {
const plaintext: EncryptableUpdates = {}
const template = {
kind: list.kind,
content: list.event?.content || "",
tags: list.publicTags.filter(nthNe(1, value)),
}
// Avoid redundant encrypt calls if possible
if (list.privateTags.some(nthEq(1, value))) {
plaintext.content = JSON.stringify(list.privateTags.filter(nthNe(1, value)))
}
return new Encryptable(template, plaintext)
}
export const addToListPublicly = (list: List, tag: string[]) => {
const template = {
kind: list.kind,
content: list.event?.content || "",
tags: append(tag, list.publicTags),
}
return new Encryptable(template, {})
}
export const addToListPrivately = (list: List, tag: string[]) => {
const template = {
kind: list.kind,
tags: list.publicTags,
}
return new Encryptable(template, {
content: JSON.stringify(append(tag, list.privateTags)),
})
}