Skip to content

Commit

Permalink
Merge pull request #69 from nostrver-se/dev
Browse files Browse the repository at this point in the history
Set generic tags on filter for requestMessages + websocket client to relay improvements
  • Loading branch information
Sebastix authored Nov 5, 2024
2 parents 5ecb5b2 + 90dc8b9 commit 3f42292
Show file tree
Hide file tree
Showing 10 changed files with 228 additions and 24 deletions.
18 changes: 12 additions & 6 deletions src/Examples/publish-event.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use swentel\nostr\Key\Key;
use swentel\nostr\Message\EventMessage;
use swentel\nostr\Relay\Relay;
use swentel\nostr\Request\Request;
use swentel\nostr\Sign\Sign;

try {
Expand All @@ -28,13 +29,18 @@
$relay = new Relay('wss://relay.nostr.band');
$eventMessage = new EventMessage($note);
$relay->setMessage($eventMessage);
/** @var \swentel\nostr\RelayResponse\RelayResponse $response */
$response = $relay->send();
$request = new Request($relay, $eventMessage);
$response = $request->send();
// Handle response.
if ($response->isSuccess) {
print 'The event has been transmitted to the relay' . PHP_EOL;
$eventId = $response->eventId;
// Now we could request the event with this id.
foreach ($response as $relayUrl => $relayResponses) {
foreach ($relayResponses as $relayResponse) {
if ($relayResponse->isSuccess) {
print 'The event has been transmitted to the relay ' . $relayUrl . PHP_EOL;
$eventId = $relayResponse->eventId;
print 'The received event id from the relay: ' . $relayResponse->eventId;
// Now we could request the event with this id.
}
}
}
} catch (Exception $e) {
print 'Exception error: ' . $e->getMessage() . PHP_EOL;
Expand Down
73 changes: 73 additions & 0 deletions src/Examples/request-events-filtered-with-tags.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

declare(strict_types=1);

use swentel\nostr\Filter\Filter;
use swentel\nostr\Message\RequestMessage;
use swentel\nostr\Relay\Relay;
use swentel\nostr\RelayResponse\RelayResponse;
use swentel\nostr\RelayResponse\RelayResponseEvent;
use swentel\nostr\Request\Request;
use swentel\nostr\Subscription\Subscription;

require __DIR__ . '/../../vendor/autoload.php';

try {
$subscription = new Subscription();
$subscriptionId = $subscription->setId();

$filter1 = new Filter();
$filter1->setKinds([1]);
$filter1->setLimit(25);
/**
* Please have a look at this overview with tags you can use according to the Nostr NIPs:
* https://nips.nostr.com/#standardized-tags
*/
// Apply multiple tags to the filter.
$filter1->setTags(
[
'#t' => ['PHP', 'Drupal'],
'#p' => ['06639a386c9c1014217622ccbcf40908c4f1a0c33e23f8d6d68f4abf655f8f71'],
],
);
// Apply a single tag to the filter which in this case will be appended to the #t tag.
$filter1->setTag('#t', ['Wordpress']);
// Apply an e-tag.
//$filter1->setLowercaseETags([
// '06639a386c9c1014217622ccbcf40908c4f1a0c33e23f8d6d68f4abf655f8f71'
//]);
// Apply a p-tag.
//$filter1->setLowercasePTags([
// '06639a386c9c1014217622ccbcf40908c4f1a0c33e23f8d6d68f4abf655f8f71'
//]);
/**
* If you're using multiple conditions in one filter, these conditions are interpreted as && (AND) conditions.
* If you would like to use || (OR) conditions, you should use multiple filters.
*/
$filters = [$filter1];
$requestMessage = new RequestMessage($subscriptionId, $filters);
$relay = new Relay('wss://relay.nostr.band');
$request = new Request($relay, $requestMessage);
$response = $request->send();

/**
* @var string $relayUrl
* The relay URL.
* @var object $relayResponse
* RelayResponse which will contain the messages returned by the relay.
* Each message will also contain the event.
*/
foreach ($response as $relayUrl => $relayResponses) {
print 'Received ' . count($response[$relayUrl]) . ' message(s) received from relay ' . $relayUrl . PHP_EOL;
/** @var RelayResponse $relayResponse */
foreach ($relayResponses as $relayResponse) {
if ($relayResponse instanceof RelayResponseEvent) {
if (isset($relayResponse->event->content)) {
print $relayResponse->event->content . PHP_EOL;
}
}
}
}
} catch (Exception $e) {
print 'Exception error: ' . $e->getMessage() . PHP_EOL;
}
2 changes: 1 addition & 1 deletion src/Examples/request-events-from-multiple-relays.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,5 @@
}
}
} catch (Exception $e) {
echo $e->getMessage();
print $e->getMessage() . PHP_EOL;
}
10 changes: 5 additions & 5 deletions src/Examples/request-events-with-auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@
$request = new Request($relay, $requestMessage);
$response = $request->send();

foreach ($response as $relay => $messages) {
foreach ($response as $relay => $relayResponses) {
print 'Received ' . count($response[$relay]) . ' message(s) received from relay ' . $relay . PHP_EOL;
foreach ($messages as $message) {
print $message->type . ': ' . $message->message . PHP_EOL;
if ($message instanceof RelayResponseEvent) {
$rawEvent = $message->event;
foreach ($relayResponses as $relayResponse) {
print 'Relay response ' . $relayResponse->type . ': ' . $relayResponse->message . PHP_EOL;
if ($relayResponse instanceof RelayResponseEvent) {
$rawEvent = $relayResponse->event;
$event = new Event();
$event->setId($rawEvent->id);
$event->setPublicKey($rawEvent->pubkey);
Expand Down
12 changes: 6 additions & 6 deletions src/Examples/request-events.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,19 @@
/**
* @var string $relayUrl
* The relay URL.
* @var object $relayResponses
* RelayResponses which will contain the messages returned by the relay.
* @var object $relayResponse
* RelayResponse which will contain the messages returned by the relay.
* Each message will also contain the event.
*/
foreach ($response as $relayUrl => $relayResponses) {
print 'Received ' . count($response[$relayUrl]) . ' message(s) received from relay ' . $relayUrl . PHP_EOL;
/** @var \swentel\nostr\RelayResponse\RelayResponseEvent $message */
foreach ($relayResponses as $message) {
if (isset($message->event->content)) {
print $message->event->content . PHP_EOL;
foreach ($relayResponses as $relayResponse) {
if (isset($relayResponse->event->content)) {
print $relayResponse->event->content . PHP_EOL;
}
}
}
} catch (Exception $e) {
print 'Exception error: ' . $e->getMessage() . '\n';
print 'Exception error: ' . $e->getMessage() . PHP_EOL;
}
75 changes: 75 additions & 0 deletions src/Filter/Filter.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
use swentel\nostr\FilterInterface;
use swentel\nostr\Key\Key;

use function PHPUnit\Framework\throwException;

class Filter implements FilterInterface
{
/**
Expand All @@ -24,6 +26,11 @@ class Filter implements FilterInterface
*/
public array $kinds;

/**
* A list of tags values starting with a # followed by single letters (format: #<single-letter (a-zA-Z)>).
*/
public array $tags;

/**
* A list of #e tag values (list of event ids)
*/
Expand Down Expand Up @@ -101,6 +108,68 @@ public function setKinds(array $kinds): static
return $this;
}

/**
* Set tags for the Filter object.
* Every tag in this filter property needs to start with a #.
*
* @param array $tags
* The array of tags to set.
* @return Filter
*/
public function setTags(array $tags): static
{
foreach ($tags as $name => $value) {
if (!is_array($value)) {
$message = sprintf('Provided tag value for %s must be an array', $name);
throw new \RuntimeException($message);
}
$this->validateTagName($name);
$this->setTag($name, $value);
}
return $this;
}

/**
* Set a single tag value for the Filter object.
*
* @param string $name
* Tag name.
* @param string $value
* Tag value.
* @return Filter
*/
public function setTag(string $name, array $value): static
{
$this->validateTagName($name);
if (isset($this->{$name})) {
$this->{$name} = array_merge($this->{$name}, $value);
} else {
$this->{$name} = $value;
}
return $this;
}

/**
* Validate standardized tag.
*
* @param $tag
* Provided tag name to be validated.
* @return void
*/
private function validateTagName($tag): void
{
// Check if tag starts with #.
if (!str_starts_with($tag, '#')) {
throw new \RuntimeException('All tags must start with #');
}
// Check if tag has valid value.
$pattern = '/^#[a-z_-]+$/i';
if (!preg_match($pattern, $tag)) {
$message = sprintf('Invalid tag provided: %s', $tag);
throw new \RuntimeException($message);
}
}

/**
* Set the #e tag for the Filter object.
*
Expand Down Expand Up @@ -146,6 +215,9 @@ public function setLowercasePTags(array $ptags): static
*/
public function setSince(int $since): static
{
if (!$this->isValidTimestamp($since)) {
throw new \RuntimeException("The provided since filter is not a valid timestamp");
}
$this->since = $since;
return $this;
}
Expand All @@ -158,6 +230,9 @@ public function setSince(int $since): static
*/
public function setUntil(int $until): static
{
if (!$this->isValidTimestamp($until)) {
throw new \RuntimeException("The provided until filter is not a valid timestamp");
}
$this->until = $until;
return $this;
}
Expand Down
24 changes: 21 additions & 3 deletions src/Message/RequestMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,7 @@ public function __construct(string $subscriptionId, array $filters)
{
$this->subscriptionId = $subscriptionId;
$this->setType(MessageTypeEnum::REQUEST);
foreach ($filters as $filter) {
$this->filters[] = $filter->toArray();
}
$this->processFilters($filters);
}

/**
Expand All @@ -63,4 +61,24 @@ public function generate(): string
$requestArray = array_merge([$this->type, $this->subscriptionId], $this->filters);
return json_encode($requestArray, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}

/**
* @param array $filters
* Process filters for the request message.
* @return void
*/
private function processFilters(array $filters): void
{
/** @var Filter\Filter $filter */
foreach ($filters as $filter) {
// Process tag values from $filter->tags.
if (isset($filter->tags)) {
foreach ($filter->tags as $key => $tag) {
$filter->{$key} = [$tag];
}
unset($filter->tags);
}
$this->filters[] = $filter->toArray();
}
}
}
1 change: 1 addition & 0 deletions src/Relay/Relay.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ private function setPayload(string $payload): void
*/
public function send(): RelayResponse
{
// TODO: deprecate this and replace with $request->send($relay, $message) logic.
$this->validateUrl();

try {
Expand Down
1 change: 1 addition & 0 deletions src/Relay/RelaySet.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ public function isConnected(): bool
*/
public function send(): array
{
// TODO: deprecate this and replace with $request->send($relaySet, $message) logic.
try {
// Send message to each relay defined in this set.
/** @var Relay $relay */
Expand Down
Loading

0 comments on commit 3f42292

Please sign in to comment.