mirror of
https://github.com/Cameri/nostream.git
synced 2025-09-17 19:13:35 +02:00
feat: NIP-40 (#148)
* feat: add method for checking if event is expired * fix: tag length check * feat: add method for expiration check * feat: refactor event expiration * fix: remove stale comment * fix: remove unused method * fix: upsert/insert tests * fix: failing tests * feat: add tests for event expiration * feat: update test * feat: add nip 40 to supportedNips * chore: add expires_at column to events table * chore: use uint for expires_at --------- Co-authored-by: Ricardo Arturo Cabral Mejía <me@ricardocabral.io>
This commit is contained in:
@@ -111,7 +111,7 @@ describe('EventMessageHandler', () => {
|
||||
})
|
||||
|
||||
it('rejects event if invalid', async () => {
|
||||
isEventValidStub.returns('reason')
|
||||
isEventValidStub.resolves('reason')
|
||||
|
||||
await handler.handleMessage(message)
|
||||
|
||||
@@ -128,6 +128,28 @@ describe('EventMessageHandler', () => {
|
||||
expect(isUserAdmitted).to.have.been.calledWithExactly(event)
|
||||
expect(strategyFactoryStub).not.to.have.been.called
|
||||
})
|
||||
|
||||
it('rejects event if it is expired', async () => {
|
||||
isEventValidStub.resolves(undefined)
|
||||
|
||||
const expiredEvent = {
|
||||
...event,
|
||||
tags: [
|
||||
['expiration', '1600000'],
|
||||
],
|
||||
}
|
||||
|
||||
const expiredEventMessage: any = [MessageType.EVENT, expiredEvent]
|
||||
|
||||
await handler.handleMessage(expiredEventMessage)
|
||||
|
||||
expect(isEventValidStub).to.have.been.calledOnceWithExactly(expiredEvent)
|
||||
|
||||
expect(onMessageSpy).to.have.been.calledOnceWithExactly(
|
||||
[MessageType.OK, event.id, false, 'event is expired'],
|
||||
)
|
||||
expect(strategyExecuteStub).not.to.have.been.called
|
||||
})
|
||||
|
||||
it('does not call strategy if none given', async () => {
|
||||
isEventValidStub.returns(undefined)
|
||||
|
@@ -435,7 +435,7 @@ describe('EventRepository', () => {
|
||||
|
||||
const query = (repository as any).insert(event).toString()
|
||||
|
||||
expect(query).to.equal('insert into "events" ("event_content", "event_created_at", "event_delegator", "event_id", "event_kind", "event_pubkey", "event_signature", "event_tags", "remote_address") values (\'I\'\'ve set up mirroring between relays: https://i.imgur.com/HxCDipB.png\', 1648351380, NULL, X\'6b3cdd0302ded8068ad3f0269c74423ca4fee460f800f3d90103b63f14400407\', 1, X\'22e804d26ed16b68db5259e78449e96dab5d464c8f470bda3eb1a70467f2c793\', X\'b37adfed0e6398546d623536f9ddc92b95b7dc71927e1123266332659253ecd0ffa91ddf2c0a82a8426c5b363139d28534d6cac893b8a810149557a3f6d36768\', \'[["p","8355095016fddbe31fcf1453b26f613553e9758cf2263e190eac8fd96a3d3de9","wss://nostr-pub.wellorder.net"],["e","7377fa81fc6c7ae7f7f4ef8938d4a603f7bf98183b35ab128235cc92d4bebf96","wss://nostr-relay.untethr.me"]]\', \'::1\') on conflict do nothing')
|
||||
expect(query).to.equal('insert into "events" ("event_content", "event_created_at", "event_delegator", "event_id", "event_kind", "event_pubkey", "event_signature", "event_tags", "expires_at", "remote_address") values (\'I\'\'ve set up mirroring between relays: https://i.imgur.com/HxCDipB.png\', 1648351380, NULL, X\'6b3cdd0302ded8068ad3f0269c74423ca4fee460f800f3d90103b63f14400407\', 1, X\'22e804d26ed16b68db5259e78449e96dab5d464c8f470bda3eb1a70467f2c793\', X\'b37adfed0e6398546d623536f9ddc92b95b7dc71927e1123266332659253ecd0ffa91ddf2c0a82a8426c5b363139d28534d6cac893b8a810149557a3f6d36768\', \'[["p","8355095016fddbe31fcf1453b26f613553e9758cf2263e190eac8fd96a3d3de9","wss://nostr-pub.wellorder.net"],["e","7377fa81fc6c7ae7f7f4ef8938d4a603f7bf98183b35ab128235cc92d4bebf96","wss://nostr-relay.untethr.me"]]\', NULL, \'::1\') on conflict do nothing')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -453,7 +453,7 @@ describe('EventRepository', () => {
|
||||
it('insert stubs by pubkey & event ids', () => {
|
||||
const query = repository.insertStubs('001122', ['aabbcc', 'ddeeff']).toString()
|
||||
|
||||
expect(query).to.equal('insert into "events" ("deleted_at", "event_content", "event_created_at", "event_deduplication", "event_delegator", "event_id", "event_kind", "event_pubkey", "event_signature", "event_tags") values (\'1970-01-20T08:57:15.425Z\', \'\', 1673835, \'["001122",5]\', NULL, X\'aabbcc\', 5, X\'001122\', X\'\', \'[]\'), (\'1970-01-20T08:57:15.425Z\', \'\', 1673835, \'["001122",5]\', NULL, X\'ddeeff\', 5, X\'001122\', X\'\', \'[]\') on conflict do nothing')
|
||||
expect(query).to.equal('insert into "events" ("deleted_at", "event_content", "event_created_at", "event_deduplication", "event_delegator", "event_id", "event_kind", "event_pubkey", "event_signature", "event_tags", "expires_at") values (\'1970-01-20T08:57:15.425Z\', \'\', 1673835, \'["001122",5]\', NULL, X\'aabbcc\', 5, X\'001122\', X\'\', \'[]\', NULL), (\'1970-01-20T08:57:15.425Z\', \'\', 1673835, \'["001122",5]\', NULL, X\'ddeeff\', 5, X\'001122\', X\'\', \'[]\', NULL) on conflict do nothing')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -480,7 +480,7 @@ describe('EventRepository', () => {
|
||||
|
||||
const query = repository.upsert(event).toString()
|
||||
|
||||
expect(query).to.equal('insert into "events" ("event_content", "event_created_at", "event_deduplication", "event_delegator", "event_id", "event_kind", "event_pubkey", "event_signature", "event_tags", "remote_address") values (\'{"name":"ottman@minds.io","about":"","picture":"https://feat-2311-nostr.minds.io/icon/1002952989368913934/medium/1564498626/1564498626/1653379539"}\', 1564498626, \'["55b702c167c85eb1c2d5ab35d68bedd1a35b94c01147364d2395c2f66f35a503",0]\', NULL, X\'e527fe8b0f64a38c6877f943a9e8841074056ba72aceb31a4c85e6d10b27095a\', 0, X\'55b702c167c85eb1c2d5ab35d68bedd1a35b94c01147364d2395c2f66f35a503\', X\'d1de98733de2b412549aa64454722d9b66ab3c68e9e0d0f9c5d42e7bd54c30a06174364b683d2c8dbb386ff47f31e6cb7e2f3c3498d8819ee80421216c8309a9\', \'[]\', \'::1\') on conflict (event_pubkey, event_kind, event_deduplication) WHERE (event_kind = 0 OR event_kind = 3 OR event_kind = 41 OR (event_kind >= 10000 AND event_kind < 20000)) OR (event_kind >= 30000 AND event_kind < 40000) do update set "event_id" = X\'e527fe8b0f64a38c6877f943a9e8841074056ba72aceb31a4c85e6d10b27095a\',"event_created_at" = 1564498626,"event_tags" = \'[]\',"event_content" = \'{"name":"ottman@minds.io","about":"","picture":"https://feat-2311-nostr.minds.io/icon/1002952989368913934/medium/1564498626/1564498626/1653379539"}\',"event_signature" = X\'d1de98733de2b412549aa64454722d9b66ab3c68e9e0d0f9c5d42e7bd54c30a06174364b683d2c8dbb386ff47f31e6cb7e2f3c3498d8819ee80421216c8309a9\',"event_delegator" = NULL,"remote_address" = \'::1\' where "events"."event_created_at" < 1564498626')
|
||||
expect(query).to.equal('insert into "events" ("event_content", "event_created_at", "event_deduplication", "event_delegator", "event_id", "event_kind", "event_pubkey", "event_signature", "event_tags", "expires_at", "remote_address") values (\'{"name":"ottman@minds.io","about":"","picture":"https://feat-2311-nostr.minds.io/icon/1002952989368913934/medium/1564498626/1564498626/1653379539"}\', 1564498626, \'["55b702c167c85eb1c2d5ab35d68bedd1a35b94c01147364d2395c2f66f35a503",0]\', NULL, X\'e527fe8b0f64a38c6877f943a9e8841074056ba72aceb31a4c85e6d10b27095a\', 0, X\'55b702c167c85eb1c2d5ab35d68bedd1a35b94c01147364d2395c2f66f35a503\', X\'d1de98733de2b412549aa64454722d9b66ab3c68e9e0d0f9c5d42e7bd54c30a06174364b683d2c8dbb386ff47f31e6cb7e2f3c3498d8819ee80421216c8309a9\', \'[]\', NULL, \'::1\') on conflict (event_pubkey, event_kind, event_deduplication) WHERE (event_kind = 0 OR event_kind = 3 OR event_kind = 41 OR (event_kind >= 10000 AND event_kind < 20000)) OR (event_kind >= 30000 AND event_kind < 40000) do update set "event_id" = X\'e527fe8b0f64a38c6877f943a9e8841074056ba72aceb31a4c85e6d10b27095a\',"event_created_at" = 1564498626,"event_tags" = \'[]\',"event_content" = \'{"name":"ottman@minds.io","about":"","picture":"https://feat-2311-nostr.minds.io/icon/1002952989368913934/medium/1564498626/1564498626/1653379539"}\',"event_signature" = X\'d1de98733de2b412549aa64454722d9b66ab3c68e9e0d0f9c5d42e7bd54c30a06174364b683d2c8dbb386ff47f31e6cb7e2f3c3498d8819ee80421216c8309a9\',"event_delegator" = NULL,"remote_address" = \'::1\',"expires_at" = NULL where "events"."event_created_at" < 1564498626')
|
||||
})
|
||||
|
||||
it('replaces event based on event_pubkey, event_kind and event_deduplication', () => {
|
||||
@@ -498,7 +498,7 @@ describe('EventRepository', () => {
|
||||
|
||||
const query = repository.upsert(event).toString()
|
||||
|
||||
expect(query).to.equal('insert into "events" ("event_content", "event_created_at", "event_deduplication", "event_delegator", "event_id", "event_kind", "event_pubkey", "event_signature", "event_tags", "remote_address") values (\'{"name":"ottman@minds.io","about":"","picture":"https://feat-2311-nostr.minds.io/icon/1002952989368913934/medium/1564498626/1564498626/1653379539"}\', 1564498626, \'["deduplication"]\', NULL, X\'e527fe8b0f64a38c6877f943a9e8841074056ba72aceb31a4c85e6d10b27095a\', 0, X\'55b702c167c85eb1c2d5ab35d68bedd1a35b94c01147364d2395c2f66f35a503\', X\'d1de98733de2b412549aa64454722d9b66ab3c68e9e0d0f9c5d42e7bd54c30a06174364b683d2c8dbb386ff47f31e6cb7e2f3c3498d8819ee80421216c8309a9\', \'[]\', \'::1\') on conflict (event_pubkey, event_kind, event_deduplication) WHERE (event_kind = 0 OR event_kind = 3 OR event_kind = 41 OR (event_kind >= 10000 AND event_kind < 20000)) OR (event_kind >= 30000 AND event_kind < 40000) do update set "event_id" = X\'e527fe8b0f64a38c6877f943a9e8841074056ba72aceb31a4c85e6d10b27095a\',"event_created_at" = 1564498626,"event_tags" = \'[]\',"event_content" = \'{"name":"ottman@minds.io","about":"","picture":"https://feat-2311-nostr.minds.io/icon/1002952989368913934/medium/1564498626/1564498626/1653379539"}\',"event_signature" = X\'d1de98733de2b412549aa64454722d9b66ab3c68e9e0d0f9c5d42e7bd54c30a06174364b683d2c8dbb386ff47f31e6cb7e2f3c3498d8819ee80421216c8309a9\',"event_delegator" = NULL,"remote_address" = \'::1\' where "events"."event_created_at" < 1564498626')
|
||||
expect(query).to.equal('insert into "events" ("event_content", "event_created_at", "event_deduplication", "event_delegator", "event_id", "event_kind", "event_pubkey", "event_signature", "event_tags", "expires_at", "remote_address") values (\'{"name":"ottman@minds.io","about":"","picture":"https://feat-2311-nostr.minds.io/icon/1002952989368913934/medium/1564498626/1564498626/1653379539"}\', 1564498626, \'["deduplication"]\', NULL, X\'e527fe8b0f64a38c6877f943a9e8841074056ba72aceb31a4c85e6d10b27095a\', 0, X\'55b702c167c85eb1c2d5ab35d68bedd1a35b94c01147364d2395c2f66f35a503\', X\'d1de98733de2b412549aa64454722d9b66ab3c68e9e0d0f9c5d42e7bd54c30a06174364b683d2c8dbb386ff47f31e6cb7e2f3c3498d8819ee80421216c8309a9\', \'[]\', NULL, \'::1\') on conflict (event_pubkey, event_kind, event_deduplication) WHERE (event_kind = 0 OR event_kind = 3 OR event_kind = 41 OR (event_kind >= 10000 AND event_kind < 20000)) OR (event_kind >= 30000 AND event_kind < 40000) do update set "event_id" = X\'e527fe8b0f64a38c6877f943a9e8841074056ba72aceb31a4c85e6d10b27095a\',"event_created_at" = 1564498626,"event_tags" = \'[]\',"event_content" = \'{"name":"ottman@minds.io","about":"","picture":"https://feat-2311-nostr.minds.io/icon/1002952989368913934/medium/1564498626/1564498626/1653379539"}\',"event_signature" = X\'d1de98733de2b412549aa64454722d9b66ab3c68e9e0d0f9c5d42e7bd54c30a06174364b683d2c8dbb386ff47f31e6cb7e2f3c3498d8819ee80421216c8309a9\',"event_delegator" = NULL,"remote_address" = \'::1\',"expires_at" = NULL where "events"."event_created_at" < 1564498626')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@@ -2,6 +2,7 @@ import { expect } from 'chai'
|
||||
|
||||
import { CanonicalEvent, Event } from '../../../src/@types/event'
|
||||
import {
|
||||
getEventExpiration,
|
||||
isDelegatedEvent,
|
||||
isDelegatedEventValid,
|
||||
isDeleteEvent,
|
||||
@@ -9,6 +10,7 @@ import {
|
||||
isEventIdValid,
|
||||
isEventMatchingFilter,
|
||||
isEventSignatureValid,
|
||||
isExpiredEvent,
|
||||
isParameterizedReplaceableEvent,
|
||||
isReplaceableEvent,
|
||||
serializeEvent,
|
||||
@@ -496,3 +498,70 @@ describe('NIP-33', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
describe('NIP-40', () => {
|
||||
let event: Event
|
||||
beforeEach(() => {
|
||||
event = {
|
||||
'id': 'a080fd288b60ac2225ff2e2d815291bd730911e583e177302cc949a15dc2b2dc',
|
||||
'pubkey': '62903b1ff41559daf9ee98ef1ae67cc52f301bb5ce26d14baba3052f649c3f49',
|
||||
'created_at': 1660896109,
|
||||
'kind': 1,
|
||||
'tags': [
|
||||
[
|
||||
'delegation',
|
||||
'86f0689bd48dcd19c67a19d994f938ee34f251d8c39976290955ff585f2db42e',
|
||||
'kind=1&created_at>1640995200',
|
||||
'c33c88ba78ec3c760e49db591ac5f7b129e3887c8af7729795e85a0588007e5ac89b46549232d8f918eefd73e726cb450135314bfda419c030d0b6affe401ec1',
|
||||
],
|
||||
],
|
||||
'content': 'Hello world',
|
||||
'sig': 'cd4a3cd20dc61dcbc98324de561a07fd23b3d9702115920c0814b5fb822cc5b7c5bcdaf3fa326d24ed50c5b9c8214d66c75bae34e3a84c25e4d122afccb66eb6',
|
||||
}
|
||||
})
|
||||
|
||||
describe('getEventExpiration', () => {
|
||||
it('returns true if expiration is a safe integer', () => {
|
||||
event.tags = [
|
||||
['expiration', '160000000'],
|
||||
]
|
||||
expect(getEventExpiration(event)).to.equal(160000000)
|
||||
})
|
||||
|
||||
it('returns false if event does not have expiration tag', () => {
|
||||
event.tags = []
|
||||
expect(getEventExpiration(event)).to.be.undefined
|
||||
})
|
||||
|
||||
it('returns false if expiration is unsafe integer', () => {
|
||||
event.tags = [
|
||||
['expiration', '160000000000000000000'],
|
||||
]
|
||||
expect(getEventExpiration(event)).to.be.undefined
|
||||
})
|
||||
|
||||
it('returns false if expiration is malformed data', () => {
|
||||
event.tags = [
|
||||
['expiration', 'a'],
|
||||
]
|
||||
expect(getEventExpiration(event)).to.be.undefined
|
||||
})
|
||||
})
|
||||
|
||||
describe('isExpiredEvent', () => {
|
||||
it('returns false if event does not have tags', () => {
|
||||
event.tags = []
|
||||
expect(isExpiredEvent(event)).to.equal(false)
|
||||
})
|
||||
|
||||
it('returns false if event does not have expiration tags', () => {
|
||||
expect(isExpiredEvent(event)).to.equal(false)
|
||||
})
|
||||
|
||||
it('returns true if event is expired', () => {
|
||||
event.tags = [
|
||||
['expiration', '100000'],
|
||||
]
|
||||
expect(isExpiredEvent(event)).to.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
Reference in New Issue
Block a user