Skip to content

Commit

Permalink
Merge pull request #55 from kriptonix/read_from_relay
Browse files Browse the repository at this point in the history
* Adds the feature reading events from a relay
  • Loading branch information
Sebastix authored Jun 18, 2024
2 parents cc4df69 + 5601f87 commit f2713d5
Show file tree
Hide file tree
Showing 9 changed files with 514 additions and 0 deletions.
191 changes: 191 additions & 0 deletions src/Filter/Filter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
<?php

declare(strict_types=1);

namespace swentel\nostr\Filter;

use swentel\nostr\FilterInterface;

class Filter implements FilterInterface
{
/**
* A list of event ids
*/
public array $id;

/**
* A list of lowercase pubkeys, the pubkey of an event must be one of these
*/
public array $authors;

/**
* A list of a kind numbers
*/
public array $kinds;

/**
* A list of #e tag values (list of event ids)
*/
public array $etags;

/**
* A list of #p tag values (list of pubkeys).
*/
public array $ptags;

/**
* An integer unix timestamp in seconds, events must be newer than this to pass
*/
public int $since;

/**
* An integer unix timestamp in seconds, events must be older than this to pass
*/
public int $until;

/**
* Maximum number of events relays SHOULD return in the initial query
*/
public int $limit;

/**
* Set the authors for the Filter object.
*
* @param array $pubkey The array of authors to set.
*/
public function setAuthors(array $pubkeys): static
{
foreach($pubkeys as $key) {
if(!$this->isLowercaseHex($key)) {
throw new \RuntimeException("Author pubkeys must be an array of 64-character lowercase hex values");
}
}
$this->authors = $pubkeys;
return $this;
}

/**
* Set the kinds for the Filter object.
*
* @param array $kinds The array of kinds to set.
*/
public function setKinds(array $kinds): static
{
$this->kinds = $kinds;
return $this;
}

/**
* Set the #e tag for the Filter object.
*
* @param array $etag The array of tag to set.
*/
public function setLowercaseETags(array $etags): static
{
foreach($etags as $tag) {
if(!$this->isLowercaseHex($tag)) {
throw new \RuntimeException("#e tags must be an array of 64-character lowercase hex values");
}
}
$this->etags = $etags;
return $this;
}

/**
* Set the #p tag for the Filter object.
*
* @param array $ptag The array of tag to set.
*/
public function setLowercasePTags(array $ptags): static
{
// Check IF array contain exact 64-character lowercase hex values
foreach($ptags as $tag) {
if(!$this->isLowercaseHex($tag)) {
throw new \RuntimeException("#p tags must be an array of 64-character lowercase hex values");
}
}
$this->ptags = $ptags;
return $this;
}

/**
* Set the since for the Filter object.
*
* @param int $since The limit to set.
*/
public function setSince(int $since): static
{
$this->since = $since;
return $this;
}

/**
* Set the until for the Filter object.
*
* @param int $until The limit to set.
*/
public function setUntil(int $until): static
{
$this->until = $until;
return $this;
}

/**
* Set the limit for the Filter object.
*
* @param int $limit The limit to set.
*/
public function setLimit(int $limit): static
{
$this->limit = $limit;
return $this;
}

/**
* Check if a given string is a 64-character lowercase hexadecimal value.
*
* @param string $string The string to check.
* @return bool True if the string is a 64-character lowercase hexadecimal value, false otherwise.
*/
public function isLowercaseHex($string): bool
{
// Regular expression to match 64-character lowercase hexadecimal value
$pattern = '/^[a-f0-9]{64}$/';
// Check if the string matches the pattern
return preg_match($pattern, $string) === 1;
}

/**
* Check if a given timestamp is valid.
*
* @param mixed $timestamp The timestamp to check.
* @return bool True if the timestamp is valid, false otherwise.
*/
public function isValidTimestamp($timestamp): bool
{
// Convert the timestamp to seconds
$timestamp = (int) $timestamp;
// Check if the timestamp is valid
return ($timestamp !== 0 && $timestamp !== false && $timestamp !== -1);
}

/**
* Return an array representation of the object by iterating through its properties.
*
* @return array The array representation of the object.
*/
public function toArray(): array
{
$array = [];
foreach (get_object_vars($this) as $key => $val) {
if($key === 'etags') {
$array['#e'] = $val;
} elseif($key === 'ptags') {
$array['#p'] = $val;
} else {
$array[$key] = $val;
}
}
return $array;
}
}
80 changes: 80 additions & 0 deletions src/FilterInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

declare(strict_types=1);

namespace swentel\nostr;

interface FilterInterface
{
/**
* Set the authors for the Filter object.
*
* @param array $pubkey The array of authors to set.
*/
public function setAuthors(array $pubkey): static;

/**
* Set the kinds for the Filter object.
*
* @param array $kinds The array of kinds to set.
*/
public function setKinds(array $kinds): static;

/**
* Set the tag for the Filter object.
*
* @param array $tag The array of tag to set.
*/
public function setLowercaseETags(array $tag): static;

/**
* Set the #p tag for the Filter object.
*
* @param array $ptag The array of tag to set.
*/
public function setLowercasePTags(array $ptag): static;

/**
* Set the since for the Filter object.
*
* @param int $since The limit to set.
*/
public function setSince(int $since): static;

/**
* Set the until for the Filter object.
*
* @param int $until The limit to set.
*/
public function setUntil(int $until): static;

/**
* Set the limit for the Filter object.
*
* @param int $limit The limit to set.
*/
public function setLimit(int $limit): static;

/**
* Check if a given string is a 64-character lowercase hexadecimal value.
*
* @param string $string The string to check.
* @return bool True if the string is a 64-character lowercase hexadecimal value, false otherwise.
*/
public function isLowercaseHex($string): bool;

/**
* Check if a given timestamp is valid.
*
* @param mixed $timestamp The timestamp to check.
* @return bool True if the timestamp is valid, false otherwise.
*/
public function isValidTimestamp($timestamp): bool;

/**
* Return an array representation of the object by iterating through its properties.
*
* @return array The array representation of the object.
*/
public function toArray(): array;
}
28 changes: 28 additions & 0 deletions src/Message/CloseMessage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace swentel\nostr\Message;

use swentel\nostr\MessageInterface;

class CloseMessage implements MessageInterface
{
/**
* Subscription ID
*/
protected string $subscriptionId;

public function __construct(string $subscriptionId)
{
$this->subscriptionId = $subscriptionId;
}

/**
* {@inheritdoc}
*/
public function generate(): string
{
return '["CLOSE", "' . $this->subscriptionId . '"]';
}
}
47 changes: 47 additions & 0 deletions src/Message/RequestMessage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

namespace swentel\nostr\Message;

use swentel\nostr\MessageInterface;
use swentel\nostr\Filter;

class RequestMessage implements MessageInterface
{
/**
* An arbitrary, non-empty string of max length 64 chars
*/
protected string $subscriptionId;

/**
* Array of filters
*/
protected array $filters = [];

/**
* Constructor for the RequestMessage class.
* Initializes the subscription ID and filters array based on the provided parameters.
*
* @param string $subscriptionId The ID of the subscription
* @param array $filters An array of filters to be applied
*/
public function __construct(string $subscriptionId, array $filters)
{
$this->subscriptionId = $subscriptionId;
foreach($filters as $filter) {
$this->filters[] = $filter->toArray();
}
}

/**
* Generates a JSON-encoded request array by merging the subscription ID and filters array.
*
* @return string The JSON-encoded request array
*/
public function generate(): string
{
$requestArray = array_merge(["REQ", $this->subscriptionId], $this->filters);
return json_encode($requestArray, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
}
Loading

0 comments on commit f2713d5

Please sign in to comment.