diff --git a/spec/more_speech/article_spec.clj b/spec/more_speech/article_spec.clj index 2135db6..c4a8b33 100644 --- a/spec/more_speech/article_spec.clj +++ b/spec/more_speech/article_spec.clj @@ -50,13 +50,13 @@ (markup-article article))))) (describe "Formatting an author nickname." - (let [author-tuple ["the pubkey" "nickname"]] + (let [author-tuple [0 "nickname"]] (it "conforms to spec." (should (s/valid? ::a/author-nickname-tuple author-tuple))) (it "is properly formatted." (should= [:bold - "the pubk..." + "00000000..." :regular " - " "nickname" diff --git a/spec/more_speech/nostr/events_spec.clj b/spec/more_speech/nostr/events_spec.clj index be0db3d..62430dc 100644 --- a/spec/more_speech/nostr/events_spec.clj +++ b/spec/more_speech/nostr/events_spec.clj @@ -9,14 +9,15 @@ "pubkey" "f00d" "created_at" @now "kind" 1 - "tags" [] + "tags" [["p" "0001" "someurl"] + ["e" "0002" "anotherurl"]] "content" "the content" "sig" "dddddd"}) (with state {:application {:text-event-map {} :chronological-text-events []} }) - (it "should create map of text events by id" + (it "creates the map of text events by id" (let [state (process-text-event @state @event) event-map (get-in state [:application :text-event-map]) text-events (get-in state [:application :chronological-text-events]) @@ -30,7 +31,18 @@ (should= @now (:created-at event)) (should= "the content" (:content event)) (should= 0xdddddd (:sig event)) - (should= [] (:tags event)) + (should= [[:p 1 "someurl"] + [:e 2 "anotherurl"]] (:tags event)) )) + (it "adds references to tagged articles." + (let [state (assoc-in @state + [:application :text-event-map 2] + {:id 2}) + state (process-references state (translate-text-event @event)) + text-event-map (get-in state [:application :text-event-map]) + article (get text-event-map 2)] + (should= [0xdeadbeef] (:references article))) + ) + ) diff --git a/src/more_speech/article.clj b/src/more_speech/article.clj index 8f0660d..c210c69 100644 --- a/src/more_speech/article.clj +++ b/src/more_speech/article.clj @@ -1,5 +1,6 @@ (ns more-speech.article - (:require [clojure.spec.alpha :as s]) + (:require [clojure.spec.alpha :as s] + [more-speech.nostr.util :refer [num->hex-string]]) (:import (java.util Date) (java.text SimpleDateFormat))) @@ -15,13 +16,13 @@ (s/def ::author-pubkey string?) (s/def ::author-nickname-tuple (s/tuple ::author-pubkey ::author-nickname)) -(defn make-article [name time body] +(defn make-article [name time body thread-count] {:group "" :author name :subject "?" :time time :body body - :thread-count 1} + :thread-count thread-count} ) (defn format-time [time] @@ -63,7 +64,7 @@ (defn markup-author [[pubkey name]] [:bold - (abbreviate-key pubkey) + (abbreviate-key (num->hex-string pubkey)) :regular " - " name diff --git a/src/more_speech/nostr/events.clj b/src/more_speech/nostr/events.clj index 364019c..d6662ed 100644 --- a/src/more_speech/nostr/events.clj +++ b/src/more_speech/nostr/events.clj @@ -11,29 +11,56 @@ [name subscription-id inner-event :as decoded-msg] event {:strs [id pubkey created_at kind tags content sig]} inner-event] (condp = kind - 0 (update-in - state [:application :nicknames] - assoc pubkey (get (json/read-str content) "name" "tilt")) + 0 (let [pubkey (hex-string->num pubkey) + name (get (json/read-str content) "name" "tilt")] + (update-in + state [:application :nicknames] assoc pubkey name)) 3 (do (printf "%s: %s %s %s\n" kind (article/format-time created_at) (name-of pubkey) content) state) 1 (process-text-event state inner-event) 4 (do (printf "%s: %s %s %s\n" kind (article/format-time created_at) (name-of pubkey) content) state) (do (prn "unknown event: " event) - state) - ))) + state)))) -(defn process-text-event [state event] +(defn process-tag [[type hex arg]] + [(keyword type) + (hex-string->num hex) + arg]) + +(defn process-tags [tags] + (map process-tag tags)) + +(defn process-references [state {:keys [id tags] :as event}] + (let [e-tags (filter #(= :e (first %)) tags) + refs (map second e-tags)] + (loop [refs refs + state state] + (if (empty? refs) + state + (let [referent-path [:application :text-event-map (first refs)]] + (if (nil? (get-in state referent-path)) + (recur (rest refs) state) + (recur (rest refs) + (update-in + state + (conj referent-path :references) + conj id)))))))) + +(defn translate-text-event [event] (let [id (hex-string->num (get event "id")) pubkey (hex-string->num (get event "pubkey")) - sig (hex-string->num (get event "sig")) - new-event {:id id - :pubkey pubkey - :created-at (get event "created_at") - :content (get event "content") - :sig sig - :tags (get event "tags")} - state (assoc-in state [:application :text-event-map id] new-event) + sig (hex-string->num (get event "sig"))] + {:id id + :pubkey pubkey + :created-at (get event "created_at") + :content (get event "content") + :sig sig + :tags (process-tags (get event "tags"))})) + +(defn process-text-event [state event] + (let [event (translate-text-event event) + id (:id event) + state (assoc-in state [:application :text-event-map id] event) state (update-in state [:application :chronological-text-events] conj id)] - state - )) \ No newline at end of file + (process-references state event))) \ No newline at end of file diff --git a/src/more_speech/ui/article_window.clj b/src/more_speech/ui/article_window.clj index 2d4296f..8e720ae 100644 --- a/src/more_speech/ui/article_window.clj +++ b/src/more_speech/ui/article_window.clj @@ -71,9 +71,10 @@ cursor (let [article-id (first articles) text-event (get article-map article-id) - {:keys [pubkey created-at content]} text-event + {:keys [pubkey created-at content references]} text-event name (get nicknames pubkey (num->hex-string pubkey)) - article (a/make-article name created-at content)] + ref-count (count references) + article (a/make-article name created-at content ref-count)] (recur (draw-article window cursor article) (rest articles)))))))