From dac337681dca6166b3232d514306bfed054e1fea Mon Sep 17 00:00:00 2001
From: Silberengel <silberengel7@protonmail.com>
Date: Tue, 17 Dec 2024 21:11:33 -0800
Subject: [PATCH] Implement a tags

---
 README.md               | 11 +++----
 src/BookEvent.php       | 66 ++++++++++++++++++++++++++++++++++++++---
 src/IntegrationTest.php | 10 +++----
 src/SectionEvent.php    | 18 +++++++----
 4 files changed, 85 insertions(+), 20 deletions(-)

diff --git a/README.md b/README.md
index 88bf224..1792ab6 100644
--- a/README.md
+++ b/README.md
@@ -12,8 +12,9 @@ Then run ```composer install``` to download the dependencies to a *vendor* folde
 ## Directions
 
 1. Open the folder *user*, create the file *nostr-private.key* and add your nsec to it.
-2. Then edit the file *relays.yml* containing your list of relays. We recommend keeping wss://thecitadel.nostr1.com in your list and adding at least one other, that you have write access to. If you remove all relays, the Citadel relay will be used as default.
-3. Return to the main/upper folder, create an Asciidoc file entitled something like *MyShortBookTitle.adoc* and have it formatted with precisely two levels of headers.
+2. Then edit the file *relays.yml* containing your list of relays. We recommend keeping wss://thecitadel.nostr1.com in your list and adding at least one other, that you have write access to. If you remove all relays, the Citadel relay will be used as default. ```a``` tags will always contain thecitadel relay as relay hint.
+3. Decide whether you want your 30040 index to contain ```e``` tags or the newer ```a``` tag version (according to NIP-62). This is denoted by adding the corresponding letter to the end of the command line arguments. I recommend using ```a```.
+4. Return to the main/upper folder, create an Asciidoc file entitled something like *MyShortBookTitle.adoc* and have it formatted with precisely two levels of headers.
 
 ```
 = title you want as the full book title (mind the space after the hashtag)
@@ -23,9 +24,9 @@ text that you want displayed as content
 more text
 ```
 
-4. On the command line, write ```php createBook.php MyShortBookTitle.adoc "Author Name" "book version"``` and press Enter. Make sure to replace the filename with the short title you want to use and the author name with the name or npub of the person/entity that should be listed as the author in the 30040 event. The book version is the edition, translation, etc. of the book.
-5. All of the event metadata will be added to the *eventsCreated.txt* file.
-6. The 30040 eventID will be sent to stdout (usually the command line) in the form of an njump hyperlink. The link will not work, if you wrote to a local relay, but you can still see the eventID.
+5. On the command line, write ```php createBook.php MyShortBookTitle.adoc "Author Name" "book version" a``` and press Enter. Make sure to replace the filename with the short title you want to use and the author name with the name or npub of the person/entity that should be listed as the author in the 30040 event. The book version is the edition, translation, etc. of the book. The _a_ denotes that you want the replaceable ```a``` tags.
+6. All of the event metadata will be added to the *eventsCreated.txt* file.
+7. The 30040 eventID will be sent to stdout (usually the command line) in the form of an njump hyperlink. The link will not work, if you wrote to a local relay, but you can still see the eventID.
 
 ## Integration Test
 
diff --git a/src/BookEvent.php b/src/BookEvent.php
index 4bcafa8..66fd7cc 100644
--- a/src/BookEvent.php
+++ b/src/BookEvent.php
@@ -1,6 +1,7 @@
 <?php
 
 use swentel\nostr\Event\Event;
+use swentel\nostr\Key\Key;
 include_once 'helperFunctions.php';
 include_once 'SectionEvent.php';
 
@@ -14,6 +15,7 @@ class BookEvent{
 public $bookAuthor;
 public $bookVersion;
 public $sectionEvents = array();
+public $sectionDtags = array();
 
 // Methods
 
@@ -65,6 +67,14 @@ function get_section_events() {
   return $this->sectionEvents;
 }
 
+function set_section_dTags($sectionDtags) {
+  $this->sectionDtags[] = $sectionDtags;
+}
+
+function get_section_dTags() {
+  return $this->sectionDtags;
+}
+
 /**
  * Create an index event and hang on the associated section events
  * Returns the eventID for the section event.
@@ -112,12 +122,16 @@ function publish_book()
                 $nextSection->set_section_title($sectionTitle);
         $nextSection->set_section_d_tag(construct_d_tag($this->get_book_title()."-".$nextSection->get_section_title()."-".$sectionNum, $nextSection->get_section_author(), $nextSection->get_section_version()));
         $nextSection->set_section_content(trim(trim(strval($section), $sectionTitle)));
-      $this->set_section_events($nextSection->create_section());
+        
+        $sectionData = $nextSection->create_section();       
+        $this->set_section_events($sectionData["eventID"]);
+        $this->set_section_dTags($sectionData["dTag"]);
 
       }
 
     // write the 30040 and add the new 30041s
-    $indexID = $this->create_book();
+    if($this->bookArguments[4]==='e') $indexID = $this->create_book_with_e_tags();
+    if($this->bookArguments[4]==='a') $indexID = $this->create_book_with_a_tags();
 
     // print a njump hyperlink to the 30040
     print "https://njump.me/".$indexID.PHP_EOL;
@@ -127,12 +141,56 @@ function publish_book()
 
 /**
  * Create an index event and hang on the associated section events.
- * Returns the index event ID.
+ * Returns the index as an event.
  *
  * @param BookEvent
  * @return string $resultID
  */
-function create_book()
+function create_book_with_a_tags()
+{
+  $kind = "30040";
+
+  // get public hex key
+  $keys = new Key();
+  $keyFile = getcwd()."/user/nostr-private.key";
+  $privateBech32 = trim(file_get_contents($keyFile));
+  $privateHex = $keys->convertToHex($privateBech32);
+  $publicHex = $keys->getPublicKey($privateHex);
+
+  $tags[] = ['d', $this->get_book_d_tag()];
+  $tags[] = ['title', $this->get_book_title()];
+  $tags[] = ['author', $this->get_book_author()];
+  $tags[] = ['version', $this->get_book_version()];
+  $tags[] = ['type', 'book'];
+  $tags[] = ['auto-update', 'yes'];
+  foreach ($this->get_section_events() as &$etags) {
+    $dTag = array_shift($this->sectionDtags);
+    $tags[] = ['a', '30041:'.$publicHex.':'.$dTag, 'wss://thecitadel.nostr1.com', $etags];
+    }
+  
+  $note = new Event();
+  $note->setKind($kind);
+  $note->setTags($tags);
+  $note->setContent("");
+
+  prepare_event_data($note);
+
+  // issue the eventID, pause to prevent the relay from balking, and retry on fail
+  $i = 0;
+  do {
+    $eventID = $note->getId();
+    $i++;
+    sleep(5);
+  } while (($i <= 10) && empty($eventID));
+
+  (empty($eventID)) ? throw new InvalidArgumentException('The book eventID was not created') : $eventID;
+
+  echo "Published ".$kind." event with ID ".$eventID.PHP_EOL.PHP_EOL;
+  print_event_data($kind, $eventID, $this->get_book_d_tag());
+  return $eventID;
+}
+
+function create_book_with_e_tags()
 {
   $kind = "30040";
 
diff --git a/src/IntegrationTest.php b/src/IntegrationTest.php
index 415be01..1fbe040 100644
--- a/src/IntegrationTest.php
+++ b/src/IntegrationTest.php
@@ -10,7 +10,7 @@ final class IntegrationTest extends TestCase
     public function testSourcefileHasTwoHeaderLevels(): void
     {
         $testFile =  getcwd()."/src/testdata/AesopsFables_2Headers.adoc";
-        $testArgv = ['createBook.php', $testFile, 'Æsop', 'test version'];
+        $testArgv = ['createBook.php', $testFile, 'Æsop', 'test version with e tags', 'e'];
         $book = new BookEvent();
         $book->set_book_arguments($testArgv);
         $book->publish_book();
@@ -22,7 +22,7 @@ public function testSourcefileHasThreeHeaderLevels(): void
         $this->expectException(InvalidArgumentException::class);
 
         $testFile =  getcwd()."/src/testdata/AesopsFables_3Headers.adoc";
-        $testArgv = ['createBook.php', $testFile, 'Æsop', 'test version'];
+        $testArgv = ['createBook.php', $testFile, 'Æsop', 'test version with e tags', 'e'];
         $book = new BookEvent();
         $book->set_book_arguments($testArgv);
         $book->publish_book();
@@ -33,7 +33,7 @@ public function testSourcefileHasOneHeaderLevel(): void
         $this->expectException(InvalidArgumentException::class);
 
         $testFile =  getcwd()."/src/testdata/AesopsFables_1Header.adoc";
-        $testArgv = ['createBook.php', $testFile, 'Æsop', 'test version'];
+        $testArgv = ['createBook.php', $testFile, 'Æsop', 'test version with e tags', 'e'];
         $book = new BookEvent();
         $book->set_book_arguments($testArgv);
         $book->publish_book();
@@ -44,7 +44,7 @@ public function testSourcefileHasNoHeaders(): void
         $this->expectException(InvalidArgumentException::class);
 
         $testFile =  getcwd()."/src/testdata/AesopsFables_0Headers.adoc";
-        $testArgv = ['createBook.php', $testFile, 'Æsop', 'test version'];
+        $testArgv = ['createBook.php', $testFile, 'Æsop', 'test version with e tags', 'e'];
         $book = new BookEvent();
         $book->set_book_arguments($testArgv);
         $book->publish_book();
@@ -62,7 +62,7 @@ public function testRelayListIsEmpty(): void
 
         // make sure that book can still be printed using the default Citadel relay.
         $testFile =  getcwd()."/src/testdata/AesopsFables_2Headers.adoc";
-        $testArgv = ['createBook.php', $testFile, 'Æsop', 'test version'];
+        $testArgv = ['createBook.php', $testFile, 'Æsop', 'test version with a tags', 'a'];
         $book = new BookEvent();
         $book->set_book_arguments($testArgv);
         $book->publish_book();
diff --git a/src/SectionEvent.php b/src/SectionEvent.php
index e06921a..1817030 100644
--- a/src/SectionEvent.php
+++ b/src/SectionEvent.php
@@ -54,11 +54,11 @@ function get_section_content() {
 
 /**
  * Create a section event.
- * Returns the eventID for the section event.
+ * Returns the array containing the ID and d-tag for the section event.
  *
- * @return string $eventID
+ * @return array $result
  */
-function create_section()
+function create_section(): array
 {
   $kind = "30041";
   $note = new Event();
@@ -81,10 +81,16 @@ function create_section()
   } while (($i <= 10) && empty($eventID));
 
   (empty($eventID)) ? throw new InvalidArgumentException('The section eventID was not created') : $eventID;
-  
+ 
+  $result = array(
+    "eventID" => $eventID,
+    "dTag" => $this->get_section_d_tag()
+  );
+
   echo "Published ".$kind." event with ID ".$eventID.PHP_EOL;
-  print_event_data($kind, $eventID, $this->get_section_d_tag());
-  return $eventID;
+  print_event_data($kind, $eventID, $this->get_section_d_tag());  
+ 
+  return $result;
 
 }