Use kind 15 to send images in DMs

This commit is contained in:
Jon Staab
2025-06-03 16:46:30 -07:00
parent 55efb3fdfd
commit 43b207c4dc
5 changed files with 88 additions and 16 deletions
+69 -11
View File
@@ -1,9 +1,28 @@
<script lang="ts">
import type {Snippet} from "svelte"
import {onMount} from "svelte"
import {int, nthNe, MINUTE, sortBy, remove, formatTimestampAsDate} from "@welshman/lib"
import type {TrustedEvent, EventContent} from "@welshman/util"
import {createEvent, DIRECT_MESSAGE, INBOX_RELAYS} from "@welshman/util"
import {
int,
ms,
partition,
spec,
nthEq,
nthNe,
MINUTE,
sortBy,
remove,
formatTimestampAsDate,
} from "@welshman/lib"
import type {TrustedEvent, EventTemplate, EventContent} from "@welshman/util"
import {parse, isLink} from "@welshman/content"
import {
createEvent,
tagsFromIMeta,
getTags,
DIRECT_MESSAGE,
DIRECT_MESSAGE_FILE,
INBOX_RELAYS,
} from "@welshman/util"
import {
pubkey,
tagPubkey,
@@ -61,14 +80,53 @@
}
const onSubmit = async (params: EventContent) => {
// Remove p tags since they result in forking the conversation
const tags = [...params.tags.filter(nthNe(0, "p")), ...remove($pubkey!, pubkeys).map(tagPubkey)]
const ptags = remove($pubkey!, pubkeys).map(tagPubkey)
await sendWrapped({
pubkeys,
template: createEvent(DIRECT_MESSAGE, prependParent(parent, {...params, tags})),
delay: $userSettingValues.send_delay,
})
// Remove p tags since they result in forking the conversation
params.tags = params.tags.filter(nthNe(0, "p"))
// Add our reply quote to content
params = prependParent(parent, params)
const [imetaTags, tags] = partition(nthEq(0, "imeta"), params.tags)
const imetas = getTags("imeta", imetaTags).map(tagsFromIMeta)
const templates: EventTemplate[] = []
const buffer = []
const addTemplate = (kind: number, content: string, tags: string[][]) => {
content = content.trim()
if (content) {
templates.push(createEvent(kind, {content, tags: [...tags, ...ptags]}))
}
}
for (const p of parse(params)) {
const imeta = isLink(p)
? imetas.find(tags => tags.find(spec(["url", p.value.url.toString()])))
: undefined
if (isLink(p) && imeta) {
addTemplate(DIRECT_MESSAGE, buffer.splice(0).join(""), tags)
addTemplate(
DIRECT_MESSAGE_FILE,
p.value.url.toString(),
imeta.slice(1).filter(nthNe(0, "url")),
)
} else {
buffer.push(p.raw)
}
}
addTemplate(DIRECT_MESSAGE, buffer.splice(0).join(""), tags)
// Split the message into multiple pieces so that we can use kind 15 to send images per nip 17
// Sleep 1 second between each one to make sure timestamps are distinct
for (let i = 0; i < templates.length; i++) {
const template = templates[i]
await sendWrapped({pubkeys, template, delay: $userSettingValues.send_delay + ms(i)})
}
clearParent()
}
@@ -191,7 +249,7 @@
{/snippet}
</PageBar>
<PageContent class="flex flex-col-reverse pt-4">
<PageContent class="flex flex-col-reverse gap-2 pt-4">
<div bind:this={dynamicPadding}></div>
{#if missingInboxes.includes($pubkey!)}
<div class="py-12">
@@ -10,7 +10,7 @@
const meta =
getTags("imeta", event.tags)
.map(tagsFromIMeta)
.find(meta => getTagValue("url", meta) === url) || []
.find(meta => getTagValue("url", meta) === url) || event.tags
const key = getTagValue("decryption-key", meta)
const nonce = getTagValue("decryption-nonce", meta)
+10 -2
View File
@@ -5,7 +5,15 @@
import {Router} from "@welshman/router"
import {tracker, repository} from "@welshman/app"
import type {TrustedEvent} from "@welshman/util"
import {Address, getTagValue, DIRECT_MESSAGE, MESSAGE, THREAD, EVENT_TIME} from "@welshman/util"
import {
Address,
getTagValue,
DIRECT_MESSAGE,
DIRECT_MESSAGE_FILE,
MESSAGE,
THREAD,
EVENT_TIME,
} from "@welshman/util"
import {scrollToEvent} from "@lib/html"
import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte"
@@ -52,7 +60,7 @@
const onclick = () => {
if ($quote) {
if ($quote.kind === DIRECT_MESSAGE) {
if ($quote.kind === DIRECT_MESSAGE || $quote.kind === DIRECT_MESSAGE_FILE) {
return scrollToEvent($quote.id)
}
+4 -1
View File
@@ -29,6 +29,7 @@ import {
REACTION,
ZAP_RESPONSE,
DIRECT_MESSAGE,
DIRECT_MESSAGE_FILE,
GROUP_META,
MESSAGE,
GROUPS,
@@ -413,7 +414,9 @@ export const {
// Chats
export const chatMessages = deriveEvents(repository, {filters: [{kinds: [DIRECT_MESSAGE]}]})
export const chatMessages = deriveEvents(repository, {
filters: [{kinds: [DIRECT_MESSAGE, DIRECT_MESSAGE_FILE]}],
})
export type Chat = {
id: string
+4 -1
View File
@@ -17,6 +17,7 @@
MESSAGE,
INBOX_RELAYS,
DIRECT_MESSAGE,
DIRECT_MESSAGE_FILE,
MUTES,
FOLLOWS,
PROFILE,
@@ -177,7 +178,9 @@
return 1
}
if ([EVENT_TIME, THREAD, MESSAGE, DIRECT_MESSAGE].includes(e.kind)) {
if (
[EVENT_TIME, THREAD, MESSAGE, DIRECT_MESSAGE, DIRECT_MESSAGE_FILE].includes(e.kind)
) {
return 0.9
}