143 lines
4.3 KiB
TypeScript
143 lines
4.3 KiB
TypeScript
import type { Database } from '@db/sqlite';
|
|
import type * as nostrTools from '@nostr/tools';
|
|
import { isAddressableEvent, isReplaceableEvent } from '../utils/eventTypes.ts';
|
|
import { log } from '../utils/logs.ts';
|
|
import { parseATagQuery } from '../utils/parseATagQuery.ts';
|
|
import { sql } from '../utils/queries.ts';
|
|
|
|
export function handleDeletionEvent(
|
|
db: Database,
|
|
deletionEvent: nostrTools.VerifiedEvent,
|
|
encryptedEvent: nostrTools.VerifiedEvent,
|
|
ccnPubkey: string,
|
|
): void {
|
|
log.debug('start', {
|
|
tag: 'handleDeletionEvent',
|
|
decryptId: deletionEvent.id,
|
|
encryptedId: encryptedEvent.id,
|
|
kind: deletionEvent.kind,
|
|
ccnPubkey,
|
|
});
|
|
|
|
try {
|
|
db.run('BEGIN TRANSACTION');
|
|
log.debug('begin transaction', { tag: 'handleDeletionEvent' });
|
|
|
|
sql`
|
|
INSERT INTO events (id, original_id, pubkey, created_at, kind, content, sig, first_seen, ccn_pubkey) VALUES (
|
|
${deletionEvent.id},
|
|
${encryptedEvent.id},
|
|
${deletionEvent.pubkey},
|
|
${deletionEvent.created_at},
|
|
${deletionEvent.kind},
|
|
${deletionEvent.content},
|
|
${deletionEvent.sig},
|
|
unixepoch(),
|
|
${ccnPubkey}
|
|
)
|
|
`(db);
|
|
|
|
if (deletionEvent.tags) {
|
|
for (let i = 0; i < deletionEvent.tags.length; i++) {
|
|
const tag = sql`
|
|
INSERT INTO event_tags(event_id, tag_name, tag_index) VALUES (
|
|
${deletionEvent.id},
|
|
${deletionEvent.tags[i][0]},
|
|
${i}
|
|
) RETURNING tag_id
|
|
`(db)[0];
|
|
|
|
for (let j = 1; j < deletionEvent.tags[i].length; j++) {
|
|
sql`
|
|
INSERT INTO event_tags_values(tag_id, value_position, value) VALUES (
|
|
${tag.tag_id},
|
|
${j},
|
|
${deletionEvent.tags[i][j]}
|
|
)
|
|
`(db);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const tag of deletionEvent.tags) {
|
|
if (tag[0] === 'e' && tag[1]) {
|
|
sql`
|
|
UPDATE events
|
|
SET deleted = 1
|
|
WHERE id = ${tag[1]}
|
|
AND pubkey = ${deletionEvent.pubkey}
|
|
AND ccn_pubkey = ${ccnPubkey}
|
|
`(db);
|
|
log.debug('deleted event by id', {
|
|
tag: 'handleDeletionEvent',
|
|
eventId: tag[1],
|
|
});
|
|
} else if (tag[0] === 'a' && tag[1]) {
|
|
const { kind, pubkey, dTag } = parseATagQuery(tag[1]);
|
|
if (!kind || !pubkey) continue;
|
|
if (pubkey !== deletionEvent.pubkey) continue;
|
|
if (isReplaceableEvent(kind)) {
|
|
sql`
|
|
UPDATE events
|
|
SET deleted = 1
|
|
WHERE kind = ${kind}
|
|
AND pubkey = ${pubkey}
|
|
AND ccn_pubkey = ${ccnPubkey}
|
|
AND created_at <= ${deletionEvent.created_at}
|
|
`(db);
|
|
log.debug('deleted replaceable event', {
|
|
tag: 'handleDeletionEvent',
|
|
kind,
|
|
pubkey,
|
|
});
|
|
} else if (isAddressableEvent(kind) && dTag) {
|
|
sql`
|
|
UPDATE events
|
|
SET deleted = 1
|
|
WHERE kind = ${kind}
|
|
AND pubkey = ${pubkey}
|
|
AND ccn_pubkey = ${ccnPubkey}
|
|
AND created_at <= ${deletionEvent.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);
|
|
log.debug('deleted addressable event', {
|
|
tag: 'handleDeletionEvent',
|
|
kind,
|
|
pubkey,
|
|
dTag,
|
|
});
|
|
}
|
|
} else if (tag[0] === 'k') {
|
|
sql`
|
|
UPDATE events
|
|
SET deleted = 1
|
|
WHERE kind = ${tag[1]}
|
|
AND pubkey = ${deletionEvent.pubkey}
|
|
AND ccn_pubkey = ${ccnPubkey}
|
|
AND created_at <= ${deletionEvent.created_at}
|
|
`(db);
|
|
log.debug('deleted events of kind', {
|
|
tag: 'handleDeletionEvent',
|
|
kind: tag[1],
|
|
});
|
|
}
|
|
}
|
|
db.run('COMMIT TRANSACTION');
|
|
log.debug('committed transaction', { tag: 'handleDeletionEvent' });
|
|
} catch (e) {
|
|
db.run('ROLLBACK TRANSACTION');
|
|
log.error('transaction rolled back', {
|
|
tag: 'handleDeletionEvent',
|
|
error: e,
|
|
});
|
|
throw e;
|
|
}
|
|
log.debug('end', { tag: 'handleDeletionEvent', id: deletionEvent.id });
|
|
}
|