Add update functions to lists, document Encryptable, fix tag inheritance
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user