aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/nostr.hpp36
-rw-r--r--src/nostr_service.cpp81
-rw-r--r--test/nostr_service_test.cpp106
3 files changed, 40 insertions, 183 deletions
diff --git a/include/nostr.hpp b/include/nostr.hpp
index 5f5ce25..e450505 100644
--- a/include/nostr.hpp
+++ b/include/nostr.hpp
@@ -163,15 +163,6 @@ public:
/**
* @brief Queries all open relay connections for events matching the given set of filters.
* @param filters The filters to use for the query.
- * @returns The ID of the subscription created for the query.
- * @remarks The service will store a limited number of events returned from the relay for the
- * given filters. These events may be retrieved via `getNewEvents`.
- */
- std::string queryRelays(std::shared_ptr<Filters> filters);
-
- /**
- * @brief Queries all open relay connections for events matching the given set of filters.
- * @param filters The filters to use for the query.
* @param responseHandler A callable object that will be invoked each time the client receives
* an event matching the filters.
* @returns The ID of the subscription created for the query.
@@ -182,20 +173,6 @@ public:
std::string queryRelays(
std::shared_ptr<Filters> filters,
std::function<void(const std::string&, std::shared_ptr<Event>)> responseHandler);
-
- /**
- * @brief Get any new events received since the last call to this method, across all
- * subscriptions.
- * @returns A pointer to a vector of new events.
- */
- std::vector<std::shared_ptr<Event>> getNewEvents();
-
- /**
- * @brief Get any new events received since the last call to this method, for the given
- * subscription.
- * @returns A pointer to a vector of new events.
- */
- std::vector<std::shared_ptr<Event>> getNewEvents(std::string subscriptionId);
/**
* @brief Closes the subscription with the given ID on all open relay connections.
@@ -238,10 +215,6 @@ private:
RelayList _activeRelays;
///< A map from relay URIs to the subscription IDs open on each relay.
std::unordered_map<std::string, std::vector<std::string>> _subscriptions;
- ///< A map from subscription IDs to the events returned by the relays for each subscription.
- std::unordered_map<std::string, std::vector<std::shared_ptr<Event>>> _events;
- ///< A map from the subscription IDs to the ID of the latest read event for each subscription.
- std::unordered_map<std::string, std::string> _lastRead;
/**
* @brief Determines which of the given relays are currently connected.
@@ -301,15 +274,6 @@ private:
void onMessage(
std::string message,
std::function<void(const std::string&, std::shared_ptr<Event>)> eventHandler);
-
- /**
- * @brief A default message handler for events returned from relay queries.
- * @param subscriptionId The ID of the subscription for which the event was received.
- * @param event The event received from the relay.
- * @remark By default, new events are stored in a map of subscription IDs to vectors of events.
- * Events are retrieved by calling `getNewEvents` or `getNewEvents(subscriptionId)`.
- */
- void onEvent(std::string subscriptionId, std::shared_ptr<Event> event);
};
class ISigner
diff --git a/src/nostr_service.cpp b/src/nostr_service.cpp
index d1744e3..614e64f 100644
--- a/src/nostr_service.cpp
+++ b/src/nostr_service.cpp
@@ -179,14 +179,6 @@ tuple<RelayList, RelayList> NostrService::publishEvent(shared_ptr<Event> event)
return make_tuple(successfulRelays, failedRelays);
};
-string NostrService::queryRelays(shared_ptr<Filters> filters)
-{
- return this->queryRelays(filters, [this](string subscriptionId, shared_ptr<Event> event) {
- this->_lastRead[subscriptionId] = event->id;
- this->onEvent(subscriptionId, event);
- });
-};
-
string NostrService::queryRelays(
shared_ptr<Filters> filters,
function<void(const string&, shared_ptr<Event>)> responseHandler)
@@ -242,52 +234,6 @@ string NostrService::queryRelays(
return subscriptionId;
};
-vector<shared_ptr<Event>> NostrService::getNewEvents()
-{
- vector<shared_ptr<Event>> newEvents;
-
- for (auto& [subscriptionId, events] : this->_events)
- {
- vector<shared_ptr<Event>> subscriptionEvents = this->getNewEvents(subscriptionId);
- newEvents.insert(newEvents.end(), subscriptionEvents.begin(), subscriptionEvents.end());
- }
-
- return newEvents;
-};
-
-vector<shared_ptr<Event>> NostrService::getNewEvents(string subscriptionId)
-{
- if (this->_events.find(subscriptionId) == this->_events.end())
- {
- PLOG_ERROR << "No events found for subscription: " << subscriptionId;
- throw out_of_range("No events found for subscription: " + subscriptionId);
- }
-
- if (this->_lastRead.find(subscriptionId) == this->_lastRead.end())
- {
- PLOG_ERROR << "No last read event ID found for subscription: " << subscriptionId;
- throw out_of_range("No last read event ID found for subscription: " + subscriptionId);
- }
-
- lock_guard<mutex> lock(this->_propertyMutex);
- vector<shared_ptr<Event>> newEvents;
- vector<shared_ptr<Event>> receivedEvents = this->_events[subscriptionId];
- vector<shared_ptr<Event>>::iterator eventIt = find_if(
- receivedEvents.begin(),
- receivedEvents.end(),
- [this,subscriptionId](shared_ptr<Event> event) {
- return event->id == this->_lastRead[subscriptionId];
- }) + 1;
-
- while (eventIt != receivedEvents.end())
- {
- newEvents.push_back(move(*eventIt));
- eventIt++;
- }
-
- return newEvents;
-};
-
tuple<RelayList, RelayList> NostrService::closeSubscription(string subscriptionId)
{
RelayList successfulRelays;
@@ -523,31 +469,4 @@ void NostrService::onMessage(
throw je;
}
};
-
-void NostrService::onEvent(string subscriptionId, shared_ptr<Event> event)
-{
- lock_guard<mutex> lock(this->_propertyMutex);
- this->_events[subscriptionId].push_back(move(event));
- PLOG_INFO << "Received event for subscription: " << subscriptionId;
-
- // To protect memory, only keep a limited number of events per subscription.
- while (this->_events[subscriptionId].size() > NostrService::MAX_EVENTS_PER_SUBSCRIPTION)
- {
- auto events = this->_events[subscriptionId];
- auto eventIt = find_if(
- events.begin(),
- events.end(),
- [this, subscriptionId](shared_ptr<Event> event) {
- return event->id == this->_lastRead[subscriptionId];
- });
-
- if (eventIt == events.begin())
- {
- eventIt++;
- }
-
- this->_lastRead[subscriptionId] = (*eventIt)->id;
- _events[subscriptionId].erase(_events[subscriptionId].begin());
- }
-};
} // namespace nostr
diff --git a/test/nostr_service_test.cpp b/test/nostr_service_test.cpp
index 71af093..7adda7e 100644
--- a/test/nostr_service_test.cpp
+++ b/test/nostr_service_test.cpp
@@ -54,7 +54,7 @@ public:
"wss://nostr.thesamecat.io"
};
- static const nostr::Event getTestEvent()
+ static const nostr::Event getTextNoteTestEvent()
{
nostr::Event event;
event.pubkey = "13tn5ccv2guflxgffq4aj0hw5x39pz70zcdrfd6vym887gry38zys28dask";
@@ -70,10 +70,24 @@ public:
return event;
};
- static const string getTestEventMessage(string subscriptionId)
+ static const nostr::Event getLongFormTestEvent()
{
- auto event = make_shared<nostr::Event>(getTestEvent());
-
+ nostr::Event event;
+ event.pubkey = "13tn5ccv2guflxgffq4aj0hw5x39pz70zcdrfd6vym887gry38zys28dask";
+ event.kind = 30023;
+ event.tags =
+ {
+ { "event", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36", "wss://nostr.example.com" },
+ { "pubkey", "f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca" },
+ { "author", "30023:f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca:abcd", "wss://nostr.example.com" }
+ };
+ event.content = "Hello, World!";
+
+ return event;
+ }
+
+ static const string getTestEventMessage(shared_ptr<nostr::Event> event, string subscriptionId)
+ {
auto signer = make_unique<FakeSigner>();
signer->sign(event);
@@ -85,7 +99,7 @@ public:
return jarr.dump();
}
- static const nostr::Filters getTestFilters()
+ static const nostr::Filters getKind0And1TestFilters()
{
nostr::Filters filters;
filters.authors = {
@@ -99,6 +113,20 @@ public:
return filters;
}
+ static const nostr::Filters getKind30023TestFilters()
+ {
+ nostr::Filters filters;
+ filters.authors = {
+ "13tn5ccv2guflxgffq4aj0hw5x39pz70zcdrfd6vym887gry38zys28dask",
+ "1l9d9jh67rkwayalrxcy686aujyz5pper5kzjv8jvg8pu9v9ns4ls0xvq42",
+ "187ujhtmnv82ftg03h4heetwk3dd9mlfkf8th3fvmrk20nxk9mansuzuyla"
+ };
+ filters.kinds = { 30023 };
+ filters.limit = 5;
+
+ return filters;
+ }
+
protected:
shared_ptr<plog::ConsoleAppender<plog::TxtFormatter>> testAppender;
shared_ptr<MockWebSocketClient> mockClient;
@@ -398,7 +426,7 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_AllSuccesses)
return make_tuple(uri, true);
}));
- auto testEvent = make_shared<nostr::Event>(getTestEvent());
+ auto testEvent = make_shared<nostr::Event>(getTextNoteTestEvent());
auto [successes, failures] = nostrService->publishEvent(testEvent);
ASSERT_EQ(successes.size(), defaultTestRelays.size());
@@ -443,7 +471,7 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_AllFailures)
return make_tuple(uri, false);
}));
- auto testEvent = make_shared<nostr::Event>(getTestEvent());
+ auto testEvent = make_shared<nostr::Event>(getTextNoteTestEvent());
auto [successes, failures] = nostrService->publishEvent(testEvent);
ASSERT_EQ(successes.size(), 0);
@@ -494,7 +522,7 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_MixedSuccessesAndFailur
return make_tuple(uri, false);
}));
- auto testEvent = make_shared<nostr::Event>(getTestEvent());
+ auto testEvent = make_shared<nostr::Event>(getTextNoteTestEvent());
auto [successes, failures] = nostrService->publishEvent(testEvent);
ASSERT_EQ(successes.size(), 1);
@@ -504,61 +532,6 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_MixedSuccessesAndFailur
ASSERT_EQ(failures[0], defaultTestRelays[1]);
};
-TEST_F(NostrServiceTest, QueryRelays_UsesDefaultHandler_AndReturnsSubscriptionId)
-{
- mutex connectionStatusMutex;
- auto connectionStatus = make_shared<unordered_map<string, bool>>();
- connectionStatus->insert({ defaultTestRelays[0], false });
- connectionStatus->insert({ defaultTestRelays[1], false });
-
- EXPECT_CALL(*mockClient, isConnected(_))
- .WillRepeatedly(Invoke([connectionStatus, &connectionStatusMutex](string uri)
- {
- lock_guard<mutex> lock(connectionStatusMutex);
- bool status = connectionStatus->at(uri);
- if (status == false)
- {
- connectionStatus->at(uri) = true;
- }
- return status;
- }));
-
- auto nostrService = make_unique<nostr::NostrService>(
- testAppender,
- mockClient,
- fakeSigner,
- defaultTestRelays);
- nostrService->openRelayConnections();
-
- auto sentSubscriptionId = make_shared<string>();
- EXPECT_CALL(*mockClient, send(_, _))
- .Times(2)
- .WillRepeatedly(Invoke([sentSubscriptionId](string message, string uri)
- {
- json jarr = json::array();
- jarr = json::parse(message);
-
- string temp = jarr[1].dump();
- if (!temp.empty() && temp[0] == '\"' && temp[temp.size() - 1] == '\"')
- {
- *sentSubscriptionId = temp.substr(1, temp.size() - 2);
- }
-
- return make_tuple(uri, true);
- }));
- EXPECT_CALL(*mockClient, receive(_, _))
- .Times(2)
- .WillRepeatedly(Invoke([sentSubscriptionId](string _, function<void(const string&)> messageHandler)
- {
- messageHandler(getTestEventMessage(*sentSubscriptionId));
- }));
-
- auto filters = make_shared<nostr::Filters>(getTestFilters());
- auto receivedSubscriptionId = nostrService->queryRelays(filters);
-
- ASSERT_STREQ(receivedSubscriptionId.c_str(), sentSubscriptionId->c_str());
-};
-
TEST_F(NostrServiceTest, QueryRelays_UsesProvidedHandler_AndReturnsSubscriptionId)
{
mutex connectionStatusMutex;
@@ -605,11 +578,12 @@ TEST_F(NostrServiceTest, QueryRelays_UsesProvidedHandler_AndReturnsSubscriptionI
.Times(2)
.WillRepeatedly(Invoke([sentSubscriptionId](string _, function<void(const string&)> messageHandler)
{
- messageHandler(getTestEventMessage(*sentSubscriptionId));
+ auto event = make_shared<nostr::Event>(getTextNoteTestEvent());
+ messageHandler(getTestEventMessage(event, *sentSubscriptionId));
}));
- auto filters = make_shared<nostr::Filters>(getTestFilters());
- nostr::Event expectedEvent = getTestEvent();
+ auto filters = make_shared<nostr::Filters>(getKind0And1TestFilters());
+ nostr::Event expectedEvent = getTextNoteTestEvent();
auto receivedSubscriptionId = nostrService->queryRelays(
filters,
[expectedEvent](const string& subscriptionId, shared_ptr<nostr::Event> event)