mirror of
https://github.com/unclebob/more-speech.git
synced 2024-09-30 10:30:56 +00:00
e-tag processing for replies is working correctly.
This commit is contained in:
parent
139e3b1f0d
commit
55a2eafa43
@ -3,6 +3,9 @@
|
||||
[more-speech.nostr.events :refer :all]
|
||||
[more-speech.nostr.elliptic-signature :as ecc]))
|
||||
|
||||
(defn hexify [n]
|
||||
(->> n (ecc/num->bytes 32) ecc/bytes->hex-string))
|
||||
|
||||
(defrecord event-handler-dummy []
|
||||
event-handler
|
||||
(handle-text-event [_ _event-id])
|
||||
@ -88,10 +91,11 @@
|
||||
|
||||
(describe "Composing outgoing events"
|
||||
(it "composes an original message."
|
||||
(let [private-key (ecc/num->bytes 64 42)
|
||||
(let [private-key (ecc/num->bytes 64 314159)
|
||||
event-state {:keys {:private-key (ecc/bytes->hex-string private-key)}}
|
||||
public-key (ecc/get-pub-key private-key)
|
||||
text "message text"
|
||||
event (compose-text-event private-key text)
|
||||
event (compose-text-event event-state text)
|
||||
{:keys [pubkey created_at kind tags content id sig]} (second event)
|
||||
now (quot (System/currentTimeMillis) 1000)]
|
||||
(should= "EVENT" (first event))
|
||||
@ -104,19 +108,46 @@
|
||||
public-key
|
||||
(ecc/hex-string->bytes sig)))))
|
||||
|
||||
(it "composes a reply."
|
||||
(it "composes a reply to a root article."
|
||||
(let [private-key (ecc/num->bytes 64 42)
|
||||
reply-to 7734
|
||||
reply-to-hex (->> reply-to (ecc/num->bytes 32) ecc/bytes->hex-string)
|
||||
event-state {:keys {:private-key (ecc/bytes->hex-string private-key)}
|
||||
:text-event-map {reply-to {:tags []}}}
|
||||
public-key (ecc/get-pub-key private-key)
|
||||
reply-to (ecc/num->bytes 32 7734)
|
||||
text "message text"
|
||||
event (compose-text-event private-key text reply-to)
|
||||
event (compose-text-event event-state text reply-to)
|
||||
{:keys [pubkey created_at kind tags content id sig]} (second event)
|
||||
now (quot (System/currentTimeMillis) 1000)]
|
||||
(should= "EVENT" (first event))
|
||||
(should= (ecc/bytes->hex-string public-key) pubkey)
|
||||
(should (<= 0 (- now created_at) 1)) ;within one second.
|
||||
(should= 1 kind)
|
||||
(should= [[:e (ecc/bytes->hex-string reply-to)]] tags)
|
||||
(should= [[:e reply-to-hex]] tags)
|
||||
(should= text content)
|
||||
(should (ecc/do-verify (ecc/hex-string->bytes id)
|
||||
public-key
|
||||
(ecc/hex-string->bytes sig)))))
|
||||
|
||||
(it "composes a reply to a non-root article."
|
||||
(let [private-key (ecc/num->bytes 64 42)
|
||||
reply-to-child 7734
|
||||
reply-to-hex (->> reply-to-child (ecc/num->bytes 32) ecc/bytes->hex-string)
|
||||
root 1952
|
||||
root-hex (->> root (ecc/num->bytes 32) ecc/bytes->hex-string)
|
||||
event-state {:keys {:private-key (ecc/bytes->hex-string private-key)}
|
||||
:text-event-map {reply-to-child {:tags [[:e root-hex]]}
|
||||
root {:tags []}}}
|
||||
public-key (ecc/get-pub-key private-key)
|
||||
text "message text"
|
||||
event (compose-text-event event-state text reply-to-child)
|
||||
{:keys [pubkey created_at kind tags content id sig]} (second event)
|
||||
now (quot (System/currentTimeMillis) 1000)]
|
||||
(should= "EVENT" (first event))
|
||||
(should= (ecc/bytes->hex-string public-key) pubkey)
|
||||
(should (<= 0 (- now created_at) 1)) ;within one second.
|
||||
(should= 1 kind)
|
||||
(should= [[:e root-hex] [:e reply-to-hex]] tags)
|
||||
(should= text content)
|
||||
(should (ecc/do-verify (ecc/hex-string->bytes id)
|
||||
public-key
|
||||
@ -124,10 +155,10 @@
|
||||
|
||||
(it "composes a message with a slash."
|
||||
(let [private-key (ecc/num->bytes 64 42)
|
||||
event-state {:keys {:private-key (ecc/bytes->hex-string private-key)}}
|
||||
public-key (ecc/get-pub-key private-key)
|
||||
reply-to nil
|
||||
text "message/text"
|
||||
event (compose-text-event private-key text reply-to)
|
||||
event (compose-text-event event-state text)
|
||||
{:keys [pubkey created_at kind tags content id sig]} (second event)
|
||||
now (quot (System/currentTimeMillis) 1000)]
|
||||
(should= "EVENT" (first event))
|
||||
@ -141,6 +172,41 @@
|
||||
(ecc/hex-string->bytes sig)))))
|
||||
)
|
||||
|
||||
(describe "get references"
|
||||
(it "given no tags, finds no references"
|
||||
(let [event {:tags []}
|
||||
[root mentions referent] (get-references event)]
|
||||
(should-be-nil root)
|
||||
(should= [] mentions)
|
||||
(should-be-nil referent)))
|
||||
|
||||
(it "given one tag, finds only the referent"
|
||||
(let [event {:tags [[:e (hexify 1)]]}
|
||||
[root mentions referent] (get-references event)]
|
||||
(should-be-nil root)
|
||||
(should= [] mentions)
|
||||
(should= 1 referent)))
|
||||
|
||||
(it "given two tags, finds root and referent"
|
||||
(let [event {:tags [[:e (hexify 1)]
|
||||
[:e (hexify 2)]]}
|
||||
[root mentions referent] (get-references event)]
|
||||
(should= 1 root)
|
||||
(should= [] mentions)
|
||||
(should= 2 referent)))
|
||||
|
||||
(it "given n>2 tags, finds root and referent"
|
||||
(let [event {:tags [[:e (hexify 1)]
|
||||
[:e (hexify 2)]
|
||||
[:e (hexify 3)]
|
||||
[:e (hexify 4)]
|
||||
[:e (hexify 5)]]}
|
||||
[root mentions referent] (get-references event)]
|
||||
(should= 1 root)
|
||||
(should= [2 3 4] mentions)
|
||||
(should= 5 referent)))
|
||||
)
|
||||
|
||||
(describe "json"
|
||||
(it "does not escape slashes"
|
||||
(should= "\"/\"" (to-json "/")))
|
||||
|
@ -1,5 +1,5 @@
|
||||
;;Stories
|
||||
;; - e and p tags for text events
|
||||
;; - p tags for text events
|
||||
;; - validate incoming messages.
|
||||
;; - Add author/date, etc. to replies.
|
||||
;; - Start checking sdefs in update.
|
||||
@ -12,7 +12,6 @@
|
||||
;;Notes:
|
||||
;; Nice debug site: https://nostr-army-knife.netlify.app
|
||||
|
||||
|
||||
(ns more-speech.core
|
||||
(:require [clojure.core.async :as async]
|
||||
[more-speech.nostr.protocol :as protocol]
|
||||
|
@ -78,24 +78,24 @@
|
||||
(defn get-references [event]
|
||||
(let [tags (:tags event)
|
||||
e-tags (filter #(= :e (first %)) tags)
|
||||
refs (map second e-tags)
|
||||
refs (map hex-string->num refs)]
|
||||
refs))
|
||||
refs (map second e-tags)
|
||||
refs (map hex-string->num refs)
|
||||
root (if (< (count refs) 2) nil (first refs))
|
||||
referent (last refs)
|
||||
mentions (drop-last (rest refs))]
|
||||
[root mentions referent]))
|
||||
|
||||
(defn process-references [state event]
|
||||
(let [refs (take 1 (get-references event))] ;; Hack. Only the first reference is counted.
|
||||
(loop [refs refs
|
||||
state state]
|
||||
(if (empty? refs)
|
||||
state
|
||||
(let [referent-path [:text-event-map (first refs)]]
|
||||
(if (nil? (get-in state referent-path))
|
||||
(recur (rest refs) state)
|
||||
(recur (rest refs)
|
||||
(update-in
|
||||
state
|
||||
(concat referent-path [:references])
|
||||
conj (:id event)))))))))
|
||||
(let [[_ _ referent] (get-references event)]
|
||||
(if (nil? referent)
|
||||
state
|
||||
(let [referent-path [:text-event-map referent]]
|
||||
(if (nil? (get-in state referent-path))
|
||||
state
|
||||
(update-in
|
||||
state
|
||||
(concat referent-path [:references])
|
||||
conj (:id event)))))))
|
||||
|
||||
(defn translate-text-event [event]
|
||||
(let [id (hex-string->num (get event "id"))
|
||||
@ -141,17 +141,18 @@
|
||||
id)
|
||||
)
|
||||
|
||||
(declare make-reply-tag)
|
||||
(declare make-reply-tags get-reply-root)
|
||||
|
||||
(defn compose-text-event
|
||||
([private-key text]
|
||||
(compose-text-event private-key text nil))
|
||||
([event-state text]
|
||||
(compose-text-event event-state text nil))
|
||||
|
||||
([private-key text reply-to]
|
||||
(let [pubkey (ecc/get-pub-key private-key)
|
||||
tags (if (some? reply-to)
|
||||
[(make-reply-tag reply-to)]
|
||||
[])
|
||||
([event-state text reply-to-or-nil]
|
||||
(let [private-key (get-in event-state [:keys :private-key])
|
||||
private-key (ecc/hex-string->bytes private-key)
|
||||
pubkey (ecc/get-pub-key private-key)
|
||||
root (get-reply-root event-state reply-to-or-nil)
|
||||
tags (make-reply-tags reply-to-or-nil root)
|
||||
content text
|
||||
now (quot (System/currentTimeMillis) 1000)
|
||||
body {:pubkey (ecc/bytes->hex-string pubkey)
|
||||
@ -167,16 +168,36 @@
|
||||
]
|
||||
["EVENT" event])))
|
||||
|
||||
(defn make-reply-tag [reply-to]
|
||||
(let [reply-to (ecc/num->bytes 32 reply-to)
|
||||
reply-to (ecc/bytes->hex-string reply-to)]
|
||||
[:e reply-to])
|
||||
(defn get-reply-root [event-state reply-to-or-nil]
|
||||
(if (nil? reply-to-or-nil)
|
||||
nil
|
||||
(loop [parent-id reply-to-or-nil
|
||||
event-map (:text-event-map event-state)]
|
||||
(let [event (get event-map parent-id)
|
||||
[_ _ referent] (get-references event)]
|
||||
(if (nil? referent)
|
||||
parent-id
|
||||
(recur referent event-map)))))
|
||||
)
|
||||
|
||||
(defn send-msg [event-state event message]
|
||||
(let [private-key (get-in event-state [:keys :private-key])
|
||||
private-key (ecc/hex-string->bytes private-key)
|
||||
reply-to (:id event)
|
||||
event (compose-text-event private-key message reply-to)
|
||||
(defn make-reply-tags
|
||||
([reply-to root]
|
||||
(if (or (nil? root) (= root reply-to))
|
||||
(make-reply-tags reply-to)
|
||||
(let [root (->> root (ecc/num->bytes 32) (ecc/bytes->hex-string))
|
||||
reply-to (->> reply-to (ecc/num->bytes 32) (ecc/bytes->hex-string))]
|
||||
[[:e root] [:e reply-to]]))
|
||||
)
|
||||
([reply-to]
|
||||
(if (nil? reply-to)
|
||||
[]
|
||||
(let [reply-to (->> reply-to (ecc/num->bytes 32) (ecc/bytes->hex-string))]
|
||||
[[:e reply-to]]))
|
||||
)
|
||||
)
|
||||
|
||||
(defn send-msg [event-state source-event-or-nil message]
|
||||
(let [reply-to-or-nil (:id source-event-or-nil)
|
||||
outgoing-event (compose-text-event event-state message reply-to-or-nil)
|
||||
send-chan (:send-chan event-state)]
|
||||
(async/>!! send-chan [:event event])))
|
||||
(async/>!! send-chan [:event outgoing-event])))
|
@ -35,6 +35,11 @@
|
||||
(add-references event)
|
||||
))
|
||||
|
||||
;; at the moment an event can appear in several places in the tree.
|
||||
;; it can be in the reply chain of an event, and it can stand alone.
|
||||
;; The node-map holds the list of nodes that correspond to the id of
|
||||
;; an event.
|
||||
|
||||
(defn add-reference [reference id]
|
||||
(loop [nodes (get-in @ui-context [:node-map reference])]
|
||||
(if (empty? nodes)
|
||||
@ -46,11 +51,10 @@
|
||||
(recur (rest nodes))))))
|
||||
|
||||
(defn add-references [event]
|
||||
(loop [references (events/get-references event)]
|
||||
(if (empty? references)
|
||||
(let [[_ _ referent] (events/get-references event)]
|
||||
(if (nil? referent)
|
||||
nil
|
||||
(do (add-reference (first references) (:id event))
|
||||
(recur (rest references))))))
|
||||
(add-reference referent (:id event)))))
|
||||
|
||||
(defn find-header-node [root id]
|
||||
(loop [children (enumeration-seq (.children root))]
|
||||
|
Loading…
Reference in New Issue
Block a user