create CCN replaceable events

This commit is contained in:
Danny Morabito 2025-03-18 16:04:38 +01:00
parent 583776d52a
commit 65c34e6811
Signed by: dannym
GPG key ID: 7CC8056A5A04557E
2 changed files with 63 additions and 20 deletions

View file

@ -9,6 +9,7 @@ import {
getCCNPubkey, getCCNPubkey,
isAddressableEvent, isAddressableEvent,
isArray, isArray,
isCCNReplaceableEvent,
isLocalhost, isLocalhost,
isReplaceableEvent, isReplaceableEvent,
isValidJSON, isValidJSON,
@ -207,6 +208,25 @@ function addEventToDb(
} }
} }
if (isCCNReplaceableEvent(decryptedEvent.kind)) {
const dTag = decryptedEvent.tags.find((tag) => tag[0] === "d")?.[1];
sql`
UPDATE events
SET replaced = 1
WHERE kind = ${decryptedEvent.kind}
AND created_at < ${decryptedEvent.created_at}
AND id IN (
SELECT event_id FROM event_tags
WHERE tag_name = 'd'
AND tag_id IN (
SELECT tag_id FROM event_tags_values
WHERE value_position = 1
AND value = ${dTag}
)
)
`(db);
}
sql` sql`
INSERT INTO events (id, original_id, pubkey, created_at, kind, content, sig, first_seen) VALUES ( INSERT INTO events (id, original_id, pubkey, created_at, kind, content, sig, first_seen) VALUES (
${decryptedEvent.id}, ${decryptedEvent.id},
@ -472,6 +492,22 @@ function handleRequest(connection: UserConnection, request: NostrClientREQ) {
const aTagInfo = parseATagQuery(tagValue); const aTagInfo = parseATagQuery(tagValue);
if (aTagInfo.dTag && aTagInfo.dTag !== "") { if (aTagInfo.dTag && aTagInfo.dTag !== "") {
if (isCCNReplaceableEvent(aTagInfo.kind)) {
// CCN replaceable event reference
query = mixQuery(
query,
sqlPartial`id IN (
SELECT e.id
FROM events e
JOIN event_tags t ON e.id = t.event_id
JOIN event_tags_values v ON t.tag_id = v.tag_id
WHERE e.kind = ${aTagInfo.kind}
AND t.tag_name = 'd'
AND v.value_position = 1
AND v.value = ${aTagInfo.dTag}
)`,
);
} else {
// Addressable event reference // Addressable event reference
query = mixQuery( query = mixQuery(
query, query,
@ -487,6 +523,7 @@ function handleRequest(connection: UserConnection, request: NostrClientREQ) {
AND v.value = ${aTagInfo.dTag} AND v.value = ${aTagInfo.dTag}
)`, )`,
); );
}
} else { } else {
// Replaceable event reference // Replaceable event reference
query = mixQuery( query = mixQuery(

View file

@ -83,13 +83,19 @@ export function isRegularEvent(kind: number): boolean {
kind === 2; kind === 2;
} }
export function parseATagQuery(aTagValue: string): { kind: number, pubkey: string, dTag?: string } { export function isCCNReplaceableEvent(kind: number): boolean {
const parts = aTagValue.split(':'); return (kind >= 60000 && kind < 65536) || kind === 0;
if (parts.length < 2) return { kind: 0, pubkey: '' }; }
export function parseATagQuery(
aTagValue: string,
): { kind: number; pubkey: string; dTag?: string } {
const parts = aTagValue.split(":");
if (parts.length < 2) return { kind: 0, pubkey: "" };
return { return {
kind: parseInt(parts[0], 10), kind: Number.parseInt(parts[0], 10),
pubkey: parts[1], pubkey: parts[1],
dTag: parts.length > 2 ? parts[2] : undefined dTag: parts.length > 2 ? parts[2] : undefined,
}; };
} }