diff --git a/spec/more_speech/ui/formatters_spec.clj b/spec/more_speech/ui/formatters_spec.clj
index 196c51b..c8737ad 100644
--- a/spec/more_speech/ui/formatters_spec.clj
+++ b/spec/more_speech/ui/formatters_spec.clj
@@ -1,12 +1,12 @@
(ns more-speech.ui.formatters-spec
- (:require [speclj.core :refer :all]
+ (:require [more-speech.config :as config]
[more-speech.db.gateway :as gateway]
[more-speech.db.in-memory :as in-memory]
- [more-speech.nostr.util :refer [hexify]]
- [more-speech.ui.formatters :refer :all]
- [more-speech.ui.formatter-util :refer :all]
[more-speech.mem :refer :all]
- [more-speech.config :as config]))
+ [more-speech.nostr.util :refer [hexify]]
+ [more-speech.ui.formatter-util :refer :all]
+ [more-speech.ui.formatters :refer :all]
+ [speclj.core :refer :all]))
(describe "Abbreviations."
(it "abbreviates pubkeys"
@@ -241,12 +241,30 @@
(segment-article "@name text")))
(it "returns an :idreference segment"
- (should= [[:idreference "@0000000000000000000000000000000000000000000000000000000000000000"] [:text " text"]]
- (segment-article "@0000000000000000000000000000000000000000000000000000000000000000 text")))
+ (should= [[:idreference "@0000000000000000000000000000000000000000000000000000000000000000"] [:text " text"]]
+ (segment-article "@0000000000000000000000000000000000000000000000000000000000000000 text")))
(it "returns a list of :text and :url and :namereference segments"
(should= [[:text "Hey "] [:namereference "@bob"] [:text " Check this "] [:url "http://nostr.com"] [:text " It's cool"]]
- (segment-article "Hey @bob Check this http://nostr.com It's cool")))
+ (segment-article "Hey @bob Check this http://nostr.com It's cool"))
+ (should= [[:namereference "npub1qq"] [:text " "]
+ [:namereference "@npub1qq"] [:text " "]
+ [:nostrnamereference "nostr:npub1qq"] [:text " "]
+ [:nostrnamereference "@nostr:npub1qq"]]
+ (segment-article "npub1qq @npub1qq nostr:npub1qq @nostr:npub1qq"))
+ (should= [[:notereference "note1qq"] [:text " "]
+ [:notereference "@note1qq"] [:text " "]
+ [:nostrnotereference "nostr:note1qq"] [:text " "]
+ [:nostrnotereference "@nostr:note1qq"]]
+ (segment-article "note1qq @note1qq nostr:note1qq @nostr:note1qq")))
+ (it "extracts text from segments"
+ (should= "name" (extract-reference "@name"))
+ (should= "npub1qq" (extract-reference "npub1qq"))
+ (should= "x" (extract-reference "nostr:x"))
+ (should= "x" (extract-reference "@nostr:x"))
+ )
+
+
)
(describe "Format article"
@@ -257,11 +275,11 @@
(should= "nostr.com" (reformat-article-into-html "https://nostr.com")))
(it "should ms-link a namereference"
- (should= "@name"
+ (should= "@name"
(reformat-article-into-html "@name")))
(it "should ms-link an idreference"
- (should= "@0000000000000000000000000000000000000000000000000000000000000000"
+ (should= "@0000000000000000000000000000000000000000000000000000000000000000"
(reformat-article-into-html "@0000000000000000000000000000000000000000000000000000000000000000")))
(it "should escape HTML entities and linkify url"
@@ -274,7 +292,6 @@
(it "should replace multiple spaces with  "
(should= "one two  three   ." (reformat-article-into-html "one two three .")))
-
)
(declare db)
@@ -337,9 +354,9 @@
(should= "(?pattern1)" (str pattern))))
(it "combines multiple patterns and names"
- (let [pattern (combine-patterns [:name1 #"pattern1"]
- [:name2 #"pattern2"])]
- (should= java.util.regex.Pattern (type pattern))
- (should= "(?pattern1)|(?pattern2)" (str pattern))))
+ (let [pattern (combine-patterns [:name1 #"pattern1"]
+ [:name2 #"pattern2"])]
+ (should= java.util.regex.Pattern (type pattern))
+ (should= "(?pattern1)|(?pattern2)" (str pattern))))
)
diff --git a/src/more_speech/config.clj b/src/more_speech/config.clj
index 304ed7b..19b8f50 100644
--- a/src/more_speech/config.clj
+++ b/src/more_speech/config.clj
@@ -56,13 +56,6 @@
(def user-configuration-filename (atom "private/user-configuration"))
(def contact-lists-filename (atom "private/ub-contacts"))
-(def npub-reference #"npub1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]+")
-(def user-reference-pattern #"(?:\@[\w\-]+)|(?:npub1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)")
-(def id-reference-pattern #"\@[0-9a-f]{64}")
-(def hex-key-pattern #"[0-9a-f]{64}")
-(def user-name-chars #"[\w\-]+")
-(def reference-pattern #"\#\[\d+\]")
-
(def proof-of-work-default 12)
(def max-nodes-per-tab 1000)
(def prune-tabs-frequency-in-minutes 60)
@@ -77,10 +70,21 @@
;; https://daringfireball.net/2010/07/improved_regex_for_matching_urls
(def url-pattern #"(?i)\b(?:(?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(?:(?:[^\s()<>]+|(?:\(?:[^\s()<>]+\)))*\))+(?:\(?:(?:[^\s()<>]+|(?:\(?:[^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))")
+(def nostr-note-reference-pattern #"(?:\@)?nostr:note1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]+")
+(def note-reference-pattern #"(?:\@)?note1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]+")
+(def nostr-user-reference-pattern #"(?:\@)?nostr:npub1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]+")
+(def user-reference-pattern #"(?:\@[\w\-]+)|(?:\@)?(?:npub1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)")
+(def id-reference-pattern #"\@[0-9a-f]{64}")
+
(def email-pattern #"[\w.-]+@[\w.-]+")
(def relay-pattern #"ws+://[\w.-]+/?")
(def lud16-pattern #"([a-z0-9-_.]+)@([a-z0-9-_.]+\.[a-z0-9-_]+)")
+(def npub-reference #"npub1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]+")
+(def hex-key-pattern #"[0-9a-f]{64}")
+(def user-name-chars #"[\w\-]+")
+(def reference-pattern #"\#\[\d+\]")
+
(def production-db :xtdb)
(def db-type (atom nil))
diff --git a/src/more_speech/nostr/protocol.clj b/src/more_speech/nostr/protocol.clj
index 7cf660d..7d66ee0 100644
--- a/src/more_speech/nostr/protocol.clj
+++ b/src/more_speech/nostr/protocol.clj
@@ -18,23 +18,38 @@
date (Date. (long time))]
(.format (SimpleDateFormat. "MM/dd/yyyy kk:mm:ss z") date)))
+(defn send-request [request close]
+ (doseq [url (keys @relays)]
+ (when (not= :read-none (get-in @relays [url :read]))
+ (let [relay (:connection (get @relays url))]
+ (when (some? relay)
+ (relay/send relay request)
+ (future (do (Thread/sleep 2000)
+ (relay/send relay close))))))))
+
+(defn- make-request-id []
+ (let [r (rand-int 1000000)]
+ (str "ms-request-" r)))
+
+(defn request-note [id]
+ (let [req-id (make-request-id)
+ request ["REQ" req-id {"kinds" [1] "ids" [(util/hexify id)]} ]
+ close ["CLOSE" req-id]]
+ (send-request request close))
+ )
+
(defn request-profiles-and-contacts-for [authors]
(let [authors (if (coll? authors) authors [authors])
hexified-authors (map util/hexify authors)
trimmed-authors (if (<= (count hexified-authors) 100)
hexified-authors
(map #(subs % 0 10) (take 1000 (shuffle hexified-authors))))
- r (rand-int 1000000)]
- (doseq [url (keys @relays)]
- (when (not= :read-none (get-in @relays [url :read]))
- (let [relay (:connection (get @relays url))]
- (when (some? relay)
- (relay/send relay
- ["REQ" (str "ms-authors-" r) {"kinds" [0 3]
- "authors" trimmed-authors}])
- (future (do (Thread/sleep 2000)
- (relay/send relay
- ["CLOSE" (str "ms-authors-" r)])))))))))
+ r (rand-int 1000000)
+ request ["REQ" (str "ms-request-" r) {"kinds" [0 3]
+ "authors" trimmed-authors}]
+ close ["CLOSE" (str "ms-request-" r)]]
+ (send-request request close)
+ ))
(defn request-contact-lists [relay]
(let [now (quot (System/currentTimeMillis) 1000)
diff --git a/src/more_speech/ui/formatters.clj b/src/more_speech/ui/formatters.clj
index 01a5802..3dc3be1 100644
--- a/src/more_speech/ui/formatters.clj
+++ b/src/more_speech/ui/formatters.clj
@@ -113,7 +113,7 @@
[reply-id _ _] (events/get-references event)
reply-mark (if (some? reply-id) "^" " ")
dm-mark (if (= 4 (:kind event)) (make-dm-mark event) "")
- zap-mark (if (some? zaps) "❗ " "")
+ zap-mark (if (some? zaps) "❗⚡ " "")
reaction-mark (make-reaction-mark event)
header-text (-> content (string/replace \newline \~) (abbreviate 130))
content (if (empty? subject)
@@ -162,7 +162,7 @@
(str "" uri "")))
(defn ms-linkify [type subject]
- (str "" subject ""))
+ (str "@" subject ""))
(defn img-ify [seg]
(str "
" (linkify seg)))
@@ -189,9 +189,13 @@
(segment-article content []))
([content segments]
- (let [patterns [[:url config/url-pattern]
+ (let [patterns [[:nostrnotereference config/nostr-note-reference-pattern]
+ [:nostrnamereference config/nostr-user-reference-pattern]
+ [:notereference config/note-reference-pattern]
[:idreference config/id-reference-pattern]
- [:namereference config/user-reference-pattern]]
+ [:namereference config/user-reference-pattern]
+
+ [:url config/url-pattern]]
pattern (apply combine-patterns patterns)
group-names (map first patterns)]
(loop [content content
@@ -220,12 +224,19 @@
:else
(concat segments (list [:text content]))))))))
+(defn extract-reference [s]
+ (cond
+ (.startsWith s "nostr:") (subs s 6)
+ (.startsWith s "@nostr:") (subs s 7)
+ (.startsWith s "@") (subs s 1)
+ :else s))
+
(defn reformat-article-into-html [article]
(let [segments (segment-article article)]
(reduce
(fn [formatted-content [seg-type seg]]
- (condp = seg-type
- :text
+ (cond
+ (= seg-type :text)
(str formatted-content
((comp
non-breaking-spaces
@@ -234,18 +245,23 @@
format-replies
) seg)
)
- :url
+
+ (= seg-type :url)
(str formatted-content (linkify seg))
- :namereference
- (str formatted-content (ms-linkify "ms-namereference" seg))
+ (or (= seg-type :namereference) (= seg-type :nostrnamereference))
+ (str formatted-content (ms-linkify "ms-namereference" (extract-reference seg)))
- :idreference
- (str formatted-content (ms-linkify "ms-idreference" seg))
+ (= seg-type :idreference)
+ (str formatted-content (ms-linkify "ms-idreference" (subs seg 1)))
- :img
+ (or (= seg-type :notereference) (= seg-type :nostrnotereference))
+ (str formatted-content (ms-linkify "ms-notereference" (extract-reference seg)))
+
+ (= seg-type :img)
(str formatted-content (img-ify seg))
+ :else
formatted-content
))
""
diff --git a/src/more_speech/ui/swing/article_panel.clj b/src/more_speech/ui/swing/article_panel.clj
index 87a436c..3b5c778 100644
--- a/src/more_speech/ui/swing/article_panel.clj
+++ b/src/more_speech/ui/swing/article_panel.clj
@@ -273,7 +273,7 @@
(text! up-arrow "👍🏻")
(text! dn-arrow "👎🏻")))
(if zapped?
- (text! zap-icon "❗ ")
+ (text! zap-icon "❗⚡ ")
(text! zap-icon ""))
(swing-util/clear-popup relays-popup)
(swing-util/clear-popup reactions-popup)
@@ -328,7 +328,8 @@
(.startsWith subject "npub")
(bech32/address->number subject)
- :else nil))
+ :else
+ (gateway/get-id-from-username (get-db) subject)))
(defn get-user-info [subject _e]
(when-let [id (get-user-id-from-subject subject)]
@@ -345,7 +346,7 @@
(defn open-link [e]
(when (= HyperlinkEvent$EventType/ACTIVATED (.getEventType e))
(when-let [url (str (.getURL e))]
- (let [[type subject] (string/split (.getDescription e) #"://")]
+ (let [[type subject] (string/split (.getDescription e) #"\:\/\/")]
(cond
(or (= type "http") (= type "https"))
(try
@@ -355,7 +356,13 @@
(log-pr 1 ex)))
(= type "ms-idreference")
- (let [id (util/unhexify (subs subject 1))]
+ (let [id (util/unhexify subject)]
+ (protocol/request-note id)
+ (swing-util/select-event id))
+
+ (= type "ms-notereference")
+ (let [id (bech32/address->number subject)]
+ (protocol/request-note id)
(swing-util/select-event id))
(= type "ms-namereference")