From d10c1036e9944236cfe147e12582ecd701eaf13f Mon Sep 17 00:00:00 2001 From: "@s.roertgen" Date: Tue, 13 Aug 2024 23:35:19 +0200 Subject: [PATCH] Deletion of lists working --- .gitignore | 15 ++++++ global.css | 3 ++ package.json | 6 ++- resources/public/css/output.css | 4 ++ src/ied/db.cljs | 4 +- src/ied/events.cljs | 78 +++++++++++++++++++++++-------- src/ied/nostr.cljs | 11 ++--- src/ied/subs.cljs | 83 +++++++++++++++++++++++++++++++-- src/ied/views.cljs | 29 ++++++------ tailwind.config.js | 9 ++++ 10 files changed, 198 insertions(+), 44 deletions(-) create mode 100644 .gitignore create mode 100644 global.css create mode 100644 tailwind.config.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d785b67 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +/out/ +/resources/public/js/compiled/ +/target/ +/*-init.clj +/*.log + +# Leiningen +/.lein-* +/.nrepl-port + +# Node.js dependencies +/node_modules/ + +# shadow-cljs cache, port files +/.shadow-cljs/ diff --git a/global.css b/global.css new file mode 100644 index 0000000..b5c61c9 --- /dev/null +++ b/global.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/package.json b/package.json index 4ff444d..9863437 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,14 @@ }, "dependencies": { "@noble/secp256k1": "^2.1.0", + "bech32": "^2.0.0", + "nostr-tools": "^2.7.2", "react": "17.0.2", "react-dom": "17.0.2" }, "devDependencies": { - "shadow-cljs": "2.26.2" + "daisyui": "^4.12.10", + "shadow-cljs": "2.26.2", + "tailwindcss": "^3.4.9" } } diff --git a/resources/public/css/output.css b/resources/public/css/output.css index b67cdfb..5744ae3 100644 --- a/resources/public/css/output.css +++ b/resources/public/css/output.css @@ -1482,6 +1482,10 @@ html { border-width: 2px; } +.p-2 { + padding: 0.5rem; +} + .filter { filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); } diff --git a/src/ied/db.cljs b/src/ied/db.cljs index b24a470..6892a02 100644 --- a/src/ied/db.cljs +++ b/src/ied/db.cljs @@ -4,9 +4,9 @@ {:name "re-frame" :current-path nil :show-add-event false - :events nil + :events #{} :pk nil - :lists nil + :list-kinds [30001 30004] :default-relays [{:name "strfry-1" :uri "http://localhost:7777" :id (random-uuid) diff --git a/src/ied/events.cljs b/src/ied/events.cljs index 4825544..5fc1d7e 100644 --- a/src/ied/events.cljs +++ b/src/ied/events.cljs @@ -10,6 +10,8 @@ [wscljs.client :as ws] [wscljs.format :as fmt])) +(def list-kinds [30001 30004]) + (re-frame/reg-event-db ::initialize-db (fn-traced [_ _] @@ -34,13 +36,13 @@ (re-frame/reg-event-fx ::save-event ;; TODO if EOSE retrieved end connection identified by uri -;; TODO make events a set (?) (fn-traced [{:keys [db]} [_ [uri raw-event]]] (let [event (nth raw-event 2 raw-event)] (println uri raw-event event) (when (and (= (first raw-event) "EVENT") - (not (some #(= (:id event) (:id %)) (get db :events {})))) + ;;(not (some #(= (:id event) (:id %)) (get db :events {}))) + ) {:db (update db :events conj event)})))) (defn handlers @@ -76,8 +78,8 @@ (let [sockets (re-frame/subscribe [::subs/sockets]) target-ws (first (filter #(= ws-uri (:uri %)) @sockets))] - (ws/send (:socket target-ws) ["REQ" "4242" {:kinds [1 30142] - :limit 10}] fmt/json) + (ws/send (:socket target-ws) ["REQ" "424242" {:kinds [30142] + :limit 10}] fmt/json) ; (ws/close (:socket (first @sockets))) ;; should be handled otherwise (?) ))) @@ -159,10 +161,9 @@ (re-frame/reg-fx ::send-to-relays-fx (fn [[sockets signedEvent]] - (println "got relays" sockets) (let [connected-sockets (filter #(= "connected" (:status %)) sockets)] (doseq [socket connected-sockets] - (.log js/console "sending to relay") + (.log js/console "sending to relay" signedEvent) (ws/send (:socket socket) ["EVENT" signedEvent] fmt/json))))) (re-frame/reg-event-db @@ -195,10 +196,12 @@ (let [event {:kind 30142 :created_at (:now cofx) :content "hello world" - :tags [["author" "" (:author resource)]]}] + :tags [["d" (:id resource)] + ["author" "" (:author resource)]]}] {::publish-resource-fx event}))) ;; TODO maybe we need some validation before publishing +;; TODO rename function to sth like send-to-relays (re-frame/reg-fx ::publish-resource-fx (fn [unsignedEvent] @@ -235,14 +238,15 @@ (defn convert-amb-to-nostr-event [json-string created_at] (let [parsed-json (js->clj (js/JSON.parse json-string) :keywordize-keys true) - tags (into [["id" (:id parsed-json)] + tags (into [["d" (:id parsed-json)] + ["id" (:id parsed-json)] ["name" (:name parsed-json)] ["image" (:image parsed-json)]] cat [(map (fn [e] ["about" (:id e) (-> e :prefLabel :de)]) (:about parsed-json)) (map (fn [e] ["inLanguage" e]) (:inLanguage parsed-json))]) event {:kind 30142 :created_at created_at - :content "Added AMB Resource" + :content "Added AMB Resource with d-tag" :tags tags}] event)) @@ -269,7 +273,7 @@ "name" (:name list)]] (map (fn [e] (cond (= 1 (:kind e)) ["e" (:id e)] - (= 30142 (:kind e)) ["a" (str "30142:" (:id e))])) + (= 30142 (:kind e)) ["a" (str "30142:" (:id e) ":" (second (first (filter #(= "d" (first %)) (:tags e)))))])) resources-to-add)) _ (.log js/console (clj->js tags)) @@ -281,20 +285,56 @@ (re-frame/reg-event-fx ::get-lists-for-npub - (fn [cofx [_ npub]] + (fn [cofx [_ [sockets npub]]] + (println "query for lists") (let [query-for-lists ["REQ" - (str "lists-for-npub") ;; TODO maybe make this more explicit later + "RAND24" ;; TODO maybe make this more explicit later {:authors [(nostr/get-pk-from-npub npub)] - :kinds [30004]}]] - {::request-from-relay query-for-lists}))) + :kinds list-kinds}]] + (.log js/console (clj->js query-for-lists)) + {::request-from-relay [sockets query-for-lists] + :dispatch [::get-deleted-lists-for-npub [sockets npub]]}))) + +(re-frame/reg-event-fx + ::get-deleted-lists-for-npub + (fn [cofx [_ [sockets npub]]] + (let [query-for-deleted-lists ["REQ" + "RAND24" ;; TODO maybe make this more explicit later + {:authors [(nostr/get-pk-from-npub npub)] + :kinds [5]}]] + (.log js/console "Query for deleted lists" (clj->js query-for-deleted-lists)) + {::request-from-relay [sockets query-for-deleted-lists]}))) (re-frame/reg-fx ::request-from-relay - (fn [query] + (fn [[sockets query]] (println "requesting from relay this query: " query) + (doall + (for [s (filter (fn [s] (= "connected" (:status s))) sockets)] + (ws/send (:socket s) query fmt/json))))) - (let [sockets @(re-frame/subscribe [::subs/sockets])] - (doall - (for [s (filter (fn [s] (= "connected" (:status s))) sockets)] - (ws/send (:socket s) query fmt/json)))))) +(re-frame/reg-event-fx + ::query-for-event-ids + (fn [db [_ [sockets event-ids]]] + (let [query ["REQ" + "RAND42" + {:ids event-ids}]] + {::request-from-relay [sockets query]}))) + +(re-frame/reg-event-fx + ::delete-list + [(re-frame/inject-cofx :now)] + (fn [cofx [_ l]] + (let [deletion-event {:kind 5 + :created_at (:now cofx) + :content "" + :tags [(cond + (= 1 (:kind l)) + ["e" (:id l)] + (some #{(:kind l)} (-> cofx :db :list-kinds)) + ["a" (str (:kind l) ":" (:pubkey l) ":" (second (first (filter + #(= "d" (first %)) + (:tags l)))))])]}] + (println deletion-event) + {::publish-resource-fx deletion-event}))) diff --git a/src/ied/nostr.cljs b/src/ied/nostr.cljs index 9df7796..2a37f11 100644 --- a/src/ied/nostr.cljs +++ b/src/ied/nostr.cljs @@ -51,17 +51,16 @@ (println serialized-event) (println id))) - (defn string-to-uint8array [s] - (let [encoder (new js/TextEncoder)] - (.encode encoder s))) +(defn string-to-uint8array [s] + (let [encoder (new js/TextEncoder)] + (.encode encoder s))) (defn get-npub-from-pk [pk] (.npubEncode nip19 pk)) (defn get-pk-from-npub [npub] - (.decode nip19 npub)) + (.-data (.decode nip19 npub))) (comment (get-npub-from-pk "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d") - (get-pk-from-npub "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6" ) - ) + (get-pk-from-npub "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6")) diff --git a/src/ied/subs.cljs b/src/ied/subs.cljs index 23ac2c2..5a5561a 100644 --- a/src/ied/subs.cljs +++ b/src/ied/subs.cljs @@ -1,6 +1,8 @@ (ns ied.subs (:require - [re-frame.core :as re-frame])) + [re-frame.core :as re-frame] + [clojure.string :as str] + [clojure.set :as set])) (re-frame/reg-sub ::name @@ -54,6 +56,81 @@ (get-in db [:route :route :route-params]))) (re-frame/reg-sub - ::lists + ::list-kinds (fn [db _] - (filter #(= 30004 (:kind %)) (:events db)))) + (:list-kinds db))) + +(defn get-d-id-from-tags + [tags] + (second (first (filter (fn [t] (= "d" (first t))) tags)))) + +(comment + (get-d-id-from-tags [["d" "https://wtcs.pressbopub/digitalliteracy/"]])) + +(defn d-id-not-in-deleted-list-ids + [d-id deleted-list-ids] + (println d-id + deleted-list-ids) + (not (contains? deleted-list-ids d-id))) + +(re-frame/reg-sub + ::lists + :<- [::list-kinds] + :<- [::events] + :<- [::deleted-list-ids] + (fn [[list-kinds events deleted-lists]] + (let [all-lists (filter #(and (some #{(:kind %)} list-kinds) + (d-id-not-in-deleted-list-ids (get-d-id-from-tags (:tags %)) deleted-lists)) + events)] + all-lists))) + +(defn extract-d-id-from-tags + [s] + (println s) + (let [parts (str/split s #":")] + (nth parts 2 nil))) + +(defn get-d-ids-from-events + [events] + (->> (into [] cat (map (fn [l] (:tags l)) events)) + (filter #(= "a" (first %))) ;; just a and e tags + (map second) ;; just the id + (map extract-d-id-from-tags) + (set))) + +(re-frame/reg-sub + ::deleted-list-ids + (fn [db _] + (let [kind-5-events (filter (fn [e] (= 5 (:kind e))) (:events db)) + deleted-list-ids (get-d-ids-from-events kind-5-events)] + (.log js/console "kind-5-events: " (clj->js kind-5-events)) + (.log js/console "Deleted list-ids " (clj->js deleted-list-ids)) + deleted-list-ids))) + +(defn extract-id-from-tags + [s] + (println s) + (let [parts (str/split s #":")] + (if (>= (count parts) 2) + (second parts) + s))) + +(re-frame/reg-sub + ::missing-events-from-lists + :<- [::events] + :<- [::lists] + (fn [[events lists]] + (let [event-ids-from-list-tags (->> (into [] cat (map (fn [l] (:tags l)) lists)) + (filter #(= (or "a" "e") (first %))) ;; just a and e tags + (map second) ;; just the id + (map extract-id-from-tags) + (set)) + event-ids (set (map #(:id %) events)) + missing-events (set/difference event-ids-from-list-tags event-ids)] + (.log js/console "Missing IDs: " (clj->js missing-events)) + missing-events))) + +(comment + (>= 2 (count (str/split "3013:fjkldj:https://jfdajdfklö" #":"))) + + (extract-id-from-tags "30142:e2d8b8e3381386976a57091199d23:https://wtcs.pressbooks.pub/digitalliteracy/")) diff --git a/src/ied/views.cljs b/src/ied/views.cljs index a621ea1..8e94f23 100644 --- a/src/ied/views.cljs +++ b/src/ied/views.cljs @@ -4,7 +4,6 @@ [ied.events :as events] [ied.routes :as routes] [ied.subs :as subs] - ["react" :as react] [reagent.core :as reagent])) ;; add resource form @@ -191,28 +190,32 @@ ;; npub (defn npub-view-panel [] - (let [route-params @(re-frame/subscribe [::subs/route-params]) - lists @(re-frame/subscribe [::subs/lists])] + (let [sockets @(re-frame/subscribe [::subs/sockets]) + route-params @(re-frame/subscribe [::subs/route-params]) + lists @(re-frame/subscribe [::subs/lists]) + missing-events-from-lists @(re-frame/subscribe [::subs/missing-events-from-lists]) + _ (when (seq missing-events-from-lists) (re-frame/dispatch [::events/query-for-event-ids [sockets missing-events-from-lists]]))] [:div [:h1 (str "Hello Npub: " (:npub route-params))] - (if (nil? lists) - [:button {:class "btn" - :on-click - #(re-frame/dispatch [::events/get-lists-for-npub (:npub route-params)])} "Load lists"] - [:div "Got some lists" + (if-not (seq lists) + [:p "No lists there...yet"] + [:div {:class "p-2"} "Got some lists" (doall (for [l lists] - [:div {:key (:id l)} - [:li - + [:div {:class "p-2" + :key (:id l)} + [:li + [:p (str "ID: " (:id l))] [:p (str "Name: " (first (filter #(= "d" (first %)) (:tags l))))] ;; TODO filter tags for already being in events ;; for all that are not send a query - [:p (str "Tags: " (:tags l))]]]))]) + [:p (str "Tags: " (:tags l))] + [:button {:class "btn btn-error" + :on-click #(re-frame/dispatch [::events/delete-list l])} "Delete List"]]]))]) [:button {:class "btn" :on-click - #(re-frame/dispatch [::events/get-lists-for-npub (:npub route-params)])} "Load lists"]])) + #(re-frame/dispatch [::events/get-lists-for-npub [sockets (:npub route-params)]])} "Load lists"]])) (defmethod routes/panels :npub-view-panel [] [npub-view-panel]) diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..09ae7e3 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,9 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ["./src/**/*.{html,js,cljs}"], + theme: { + extend: {}, + }, + plugins: [require("daisyui")], +} +