aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/client/web_socket_client.hpp6
-rw-r--r--include/nostr.hpp44
-rw-r--r--src/nostr_service.cpp26
-rw-r--r--test/nostr_service_test.cpp2
4 files changed, 65 insertions, 13 deletions
diff --git a/include/client/web_socket_client.hpp b/include/client/web_socket_client.hpp
index 4e6cb8b..f676e59 100644
--- a/include/client/web_socket_client.hpp
+++ b/include/client/web_socket_client.hpp
@@ -45,10 +45,10 @@ public:
/**
* @brief Sets up a message handler for the given server.
* @param uri The URI of the server to which the message handler should be attached.
- * @param messageHandler A callable object that will be invoked when the client receives a
- * message from the server.
+ * @param messageHandler A callable object that will be invoked with the subscription ID and
+ * the message contents when the client receives a message from the server.
*/
- virtual void receive(std::string uri, std::function<void(const std::string&)> messageHandler) = 0;
+ virtual void receive(std::string uri, std::function<void(const std::string&, const std::string&)> messageHandler) = 0;
/**
* @brief Closes the connection to the given server.
diff --git a/include/nostr.hpp b/include/nostr.hpp
index 8a9d4c9..448ad64 100644
--- a/include/nostr.hpp
+++ b/include/nostr.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <functional>
#include <mutex>
#include <string>
#include <tuple>
@@ -144,13 +145,33 @@ public:
/**
* @brief Queries all open relay connections for events matching the given set of filters.
- * @returns A tuple of `RelayList` objects, of the form `<successes, failures>`, indicating
- * to which relays the request was successfully sent, and which relays did not successfully
- * receive the request.
+ * @param filters The filters to use for the query.
+ * @returns The ID of the subscription created for the query.
+ */
+ std::string queryRelays(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.
+ */
+ std::string queryRelays(Filters filters, std::function<void(std::string, 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::tuple<RelayList, RelayList> queryRelays(Filters filters);
+ std::unique_ptr<std::vector<Event>> getNewEvents();
- // TODO: Write a method that receives events for an active subscription.
+ /**
+ * @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::unique_ptr<std::vector<Event>> getNewEvents(std::string subscriptionId);
/**
* @brief Closes the subscription with the given ID on all open relay connections.
@@ -177,11 +198,13 @@ public:
std::tuple<RelayList, RelayList> closeSubscriptions(RelayList relays);
private:
+ client::IWebSocketClient* _client;
std::mutex _propertyMutex;
RelayList _defaultRelays;
RelayList _activeRelays;
std::unordered_map<std::string, std::vector<std::string>> _subscriptions;
- client::IWebSocketClient* _client;
+ std::unordered_map<std::string, std::vector<Event>> _events;
+ std::unordered_map<std::string, std::vector<Event>::iterator> _eventIterators;
/**
* @brief Determines which of the given relays are currently connected.
@@ -234,5 +257,14 @@ private:
* @returns True if the relay has the subscription, false otherwise.
*/
bool hasSubscription(std::string relay, std::string subscriptionId);
+
+ /**
+ * @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, Event event);
};
} // namespace nostr
diff --git a/src/nostr_service.cpp b/src/nostr_service.cpp
index 3ac5177..13d5ff5 100644
--- a/src/nostr_service.cpp
+++ b/src/nostr_service.cpp
@@ -15,6 +15,7 @@ using boost::uuids::to_string;
using boost::uuids::uuid;
using nlohmann::json;
using std::async;
+using std::function;
using std::future;
using std::lock_guard;
using std::make_tuple;
@@ -147,15 +148,22 @@ tuple<RelayList, RelayList> NostrService::publishEvent(Event event)
return make_tuple(successfulRelays, failedRelays);
};
-tuple<RelayList, RelayList> NostrService::queryRelays(Filters filters)
+string NostrService::queryRelays(Filters filters)
+{
+ return this->queryRelays(filters, [this](string subscriptionId, Event event) {
+ this->onEvent(subscriptionId, event);
+ });
+};
+
+string NostrService::queryRelays(Filters filters, function<void(string, Event)> responseHandler)
{
RelayList successfulRelays;
RelayList failedRelays;
+ string subscriptionId = this->generateSubscriptionId();
vector<future<tuple<string, bool>>> requestFutures;
for (const string relay : this->_activeRelays)
{
- string subscriptionId = this->generateSubscriptionId();
this->_subscriptions[relay].push_back(subscriptionId);
string request = filters.serialize(subscriptionId);
@@ -163,6 +171,12 @@ tuple<RelayList, RelayList> NostrService::queryRelays(Filters filters)
return this->_client->send(request, relay);
});
requestFutures.push_back(move(requestFuture));
+
+ this->_client->receive(relay, [responseHandler](string subscriptionId, string message) {
+ Event event;
+ event.deserialize(message);
+ responseHandler(subscriptionId, event);
+ });
}
for (auto& publishFuture : requestFutures)
@@ -182,7 +196,7 @@ tuple<RelayList, RelayList> NostrService::queryRelays(Filters filters)
size_t successfulCount = successfulRelays.size();
PLOG_INFO << "Sent query to " << successfulCount << "/" << targetCount << " open relay connections.";
- return make_tuple(successfulRelays, failedRelays);
+ return subscriptionId;
};
tuple<RelayList, RelayList> NostrService::closeSubscription(string subscriptionId)
@@ -394,4 +408,10 @@ bool NostrService::hasSubscription(string relay, string subscriptionId)
}
return false;
};
+
+void NostrService::onEvent(string subscriptionId, Event event)
+{
+ _events[subscriptionId].push_back(event);
+ PLOG_INFO << "Received event for subscription: " << subscriptionId;
+};
} // namespace nostr
diff --git a/test/nostr_service_test.cpp b/test/nostr_service_test.cpp
index d4fc71b..2dd34d2 100644
--- a/test/nostr_service_test.cpp
+++ b/test/nostr_service_test.cpp
@@ -28,7 +28,7 @@ public:
MOCK_METHOD(void, openConnection, (string uri), (override));
MOCK_METHOD(bool, isConnected, (string uri), (override));
MOCK_METHOD((tuple<string, bool>), send, (string message, string uri), (override));
- MOCK_METHOD(void, receive, (string uri, function<void(const string&)> messageHandler), (override));
+ MOCK_METHOD(void, receive, (string uri, function<void(const string&, const string&)> messageHandler), (override));
MOCK_METHOD(void, closeConnection, (string uri), (override));
};