all repos — underbbs @ 18b7ef774abe0d4d0eb178d3214373e6fc0c01ca

decentralized social media client

we can connect to a nostr relay
Iris Lightshard nilix@nilfm.cc
PGP Signature
-----BEGIN PGP SIGNATURE-----

iHUEABYKAB0WIQT/foVVmI9pK13hPWFohAcXSWbK8wUCZiXHWQAKCRBohAcXSWbK
80PpAP9aQPb6pNQKMcCyf/SNd1aXYzM8Ekr0JMM5ZQ29cPtD5wEAnkasTuaQcXc1
O6nXHw49Vkj0557UaEd14/g2WkZPNAI=
=rIbG
-----END PGP SIGNATURE-----
commit

18b7ef774abe0d4d0eb178d3214373e6fc0c01ca

parent

03f776e634b89b40ad8674834f28910f8b743b3c

4 files changed, 189 insertions(+), 29 deletions(-)

jump to
M package-lock.jsonpackage-lock.json

@@ -9,7 +9,9 @@ "name": "underbbs",

"version": "0.0.1", "license": "ISC", "dependencies": { - "@nostr-dev-kit/ndk": "^2.7.1" + "@nostr-dev-kit/ndk": "^2.7.1", + "bech32": "^2.0.0", + "nostr-tools": "^2.5.0" }, "devDependencies": { "webpack": "^5.91.0",

@@ -84,9 +86,9 @@ "@jridgewell/sourcemap-codec": "^1.4.14"

} }, "node_modules/@noble/ciphers": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.2.0.tgz", - "integrity": "sha512-6YBxJDAapHSdd3bLDv6x2wRPwq4QFMUaB3HvljNBUTThDd12eSm7/3F+2lnfzx2jvM+S6Nsy0jEt9QbPqSwqRw==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.5.2.tgz", + "integrity": "sha512-GADtQmZCdgbnNp+daPLc3OY3ibEtGGDV/+CzeM3MFnhiQ7ELQKlsHWYq0YbYUXx4jU3/Y1erAxU6r+hwpewqmQ==", "funding": { "url": "https://paulmillr.com/funding/" }

@@ -138,6 +140,68 @@ "tseep": "^1.1.1",

"typescript-lru-cache": "^2.0.0", "utf8-buffer": "^1.0.0", "websocket-polyfill": "^0.0.3" + } + }, + "node_modules/@nostr-dev-kit/ndk/node_modules/@noble/ciphers": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.2.0.tgz", + "integrity": "sha512-6YBxJDAapHSdd3bLDv6x2wRPwq4QFMUaB3HvljNBUTThDd12eSm7/3F+2lnfzx2jvM+S6Nsy0jEt9QbPqSwqRw==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nostr-dev-kit/ndk/node_modules/@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nostr-dev-kit/ndk/node_modules/@scure/base": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", + "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@nostr-dev-kit/ndk/node_modules/nostr-tools": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-1.17.0.tgz", + "integrity": "sha512-LZmR8GEWKZeElbFV5Xte75dOeE9EFUW/QLI1Ncn3JKn0kFddDKEfBbFN8Mu4TMs+L4HR/WTPha2l+PPuRnJcMw==", + "dependencies": { + "@noble/ciphers": "0.2.0", + "@noble/curves": "1.1.0", + "@noble/hashes": "1.3.1", + "@scure/base": "1.1.1", + "@scure/bip32": "1.3.1", + "@scure/bip39": "1.2.1" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@nostr-dev-kit/ndk/node_modules/nostr-tools/node_modules/@noble/curves": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", + "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "dependencies": { + "@noble/hashes": "1.3.1" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/base": {

@@ -505,6 +569,11 @@ "dev": true,

"peerDependencies": { "ajv": "^6.9.1" } + }, + "node_modules/bech32": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" }, "node_modules/browserslist": { "version": "4.23.0",

@@ -1187,17 +1256,20 @@ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",

"dev": true }, "node_modules/nostr-tools": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-1.17.0.tgz", - "integrity": "sha512-LZmR8GEWKZeElbFV5Xte75dOeE9EFUW/QLI1Ncn3JKn0kFddDKEfBbFN8Mu4TMs+L4HR/WTPha2l+PPuRnJcMw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.5.0.tgz", + "integrity": "sha512-G02O3JYNCfhx9NDjd3NOCw/5ck8PX5hiOIhHKpsXyu49ZtZbxGH3OLP9tf0fpUZ+EVWdjIYFR689sV0i7+TOng==", "dependencies": { - "@noble/ciphers": "0.2.0", - "@noble/curves": "1.1.0", + "@noble/ciphers": "^0.5.1", + "@noble/curves": "1.2.0", "@noble/hashes": "1.3.1", "@scure/base": "1.1.1", "@scure/bip32": "1.3.1", "@scure/bip39": "1.2.1" }, + "optionalDependencies": { + "nostr-wasm": "v0.1.0" + }, "peerDependencies": { "typescript": ">=5.0.0" },

@@ -1208,11 +1280,22 @@ }

} }, "node_modules/nostr-tools/node_modules/@noble/curves": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", - "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", "dependencies": { - "@noble/hashes": "1.3.1" + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/nostr-tools/node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" }, "funding": { "url": "https://paulmillr.com/funding/"

@@ -1239,6 +1322,12 @@ "type": "individual",

"url": "https://paulmillr.com/funding/" } ] + }, + "node_modules/nostr-wasm": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/nostr-wasm/-/nostr-wasm-0.1.0.tgz", + "integrity": "sha512-78BTryCLcLYv96ONU8Ws3Q1JzjlAt+43pWQhIl86xZmWeegYCNLPml7yQ+gG3vR6V5h4XGj+TxO+SS5dsThQIA==", + "optional": true }, "node_modules/p-limit": { "version": "2.3.0",
M package.jsonpackage.json

@@ -9,7 +9,9 @@ },

"author": "", "license": "ISC", "dependencies": { - "@nostr-dev-kit/ndk": "^2.7.1" + "@nostr-dev-kit/ndk": "^2.7.1", + "bech32": "^2.0.0", + "nostr-tools": "^2.5.0" }, "devDependencies": { "webpack": "^5.91.0",
M src/adapter.jssrc/adapter.js

@@ -1,4 +1,6 @@

import NDK, {NDKPrivateKeySigner} from "@nostr-dev-kit/ndk"; +import * as nip19 from 'nostr-tools/nip19' +import { bech32 } from "bech32"; let ndk = null;

@@ -9,7 +11,7 @@ identity: null,

protocol: null, }; - adatper.init = ()=>{}; + adapter.init = ()=>{}; adapter.getInbox = ()=>{}; adapter.getFollowers = ()=>{}; adapter.getFollowing = ()=>{};

@@ -22,11 +24,13 @@ }

function toNostrAdapter(adapter, settings) { adapter.identity = { privkey: settings.privkey }; - + adapter.nickname = settings.nickname; adapter.init = ()=> { if (!ndk) { + let privkey_raw = nip19.decode(settings.privkey); + console.dir(privkey_raw); ndk = new NDK({ - signer: new NDKPrivateKeySigner(settings.privatekey), + signer: new NDKPrivateKeySigner(privkey_raw.data), explicitRelayUrls: [ settings.relays ] }); ndk.connect();
M src/index.jssrc/index.js

@@ -1,53 +1,118 @@

import adapter from "./adapter"; -let adapters = []; +window.adapters = []; function $(id) { return document.getElementById(id); } function main() { - let settings = JSON.parse(localStorage.getItem("settings"));; - if (settings != null) { - for (let s of settings.adapters) { + window.settings = JSON.parse(localStorage.getItem("settings"));; + if (window.settings != null) { + for (let s of window.settings.adapters) { switch (s.protocol) { case "nostr": let a = adapter.toNostrAdapter(adapter.createAdapter(), s); - adapters.push(a); + window.adapters.push(a); break; } } } else { console.log("no settings exist for this client"); + window.settings = { adapters: [] }; } }; function showSettings() { // tab bar hidden - let tabbar = $("tabbar"); + const tabbar = $("tabbar"); tabbar.style.display = "none"; // tabcontent to show settings ui - let tabcontent = $("tabcontent"); + const tabcontent = $("tabcontent"); - tabcontent.innerHTML = "<p>this is our settings dialogue</p>"; - tabcontent.innerHTML += "<button onclick='saveSettings()'>save</button>"; + let html = "<p>this is our settings dialogue</p>"; + html += "<button onclick='addAdapter()'>New</button>"; + html += adapters.reduce((self, a) => { + self += `<li><a href='#' onclick='editAdapter(${a.nickname})'>${a.nickname}</a></li>` + return self; + }, "<ul id='settings_adapterlist'>"); + html += "</ul>"; + html += "<button onclick='saveSettings()'>save</button>"; + tabcontent.innerHTML = html; +} + +function addAdapter() { + const tabcontent = $("tabcontent"); + // dropdown for protocol + let html = "<select id='settings_newadapter_protocolselect' onchange='fillAdapterProtocolOptions()'>"; + html += [ "nostr" ].reduce((self, p)=>{ + self += `<option value='${p}'>${p}</option>`; + return self; + }, ""); + html += "</select>"; + // depending on protocol, different fields + // nostr: privkey, initial relays + html += "<div id='settings_newadapter_protocoloptions'>"; + html += " <input id='settings_newadapter_nickname'/>"; + html += " <input id='settings_newadapter_nostr_privkey'/>"; + html += " <input id='settings_newadapter_nostr_default_relays'/>"; + html += "</div>"; + // masto/AP: server, username, pw/apikey + // save button, back button + html += "<button onclick='saveAdapter()'>Add</button>"; + html += "<button onclick='showSettings()'>Back</button>"; + tabcontent.innerHTML = html; +} + +function fillAdapterProtocolOptions() { + const proto = $("settings_newadapter_protocolselect"); + console.log(proto.options[proto.selectedIndex]); } function saveSettings() { if (window.settings) { localStorage.setItem("settings", JSON.stringify(window.settings)); } - // tab bar hidden - let tabbar = $("tabbar"); + // tab bar hidden + const tabbar = $("tabbar"); tabbar.style.display = "block"; // tabcontent to show settings ui - let tabcontent = $("tabcontent"); + const tabcontent = $("tabcontent"); tabcontent.innerHTML = ""; } +function saveAdapter() { + let self = {}; + // get selected adapter protocol + const proto = $("settings_newadapter_protocolselect"); + console.log(proto.options[proto.selectedIndex]); + + // switch protocol + switch (proto.options[proto.selectedIndex].value) { + // nostr: save privkey + // save relays + case "nostr": + const privkey = $("settings_newadapter_nostr_privkey").value; + const relays = $("settings_newadapter_nostr_default_relays").value; + const nickname = $("settings_newadapter_nickname").value; + self = { nickname: nickname, protocol: "nostr", privkey: privkey, relays: relays.split(",").map(r=>r.trim()) }; + break; + // AP/masto: whatever + case "ap": + break; + } + window.settings.adapters.push(self); + adapters.push(adapter.toNostrAdapter(adapter.createAdapter(), self)); + localStorage.setItem("settings", JSON.stringify(window.settings)); + showSettings(); +} + +window.addAdapter = addAdapter; +window.saveAdapter = saveAdapter; +window.fillAdapterProtocolOptions = fillAdapterProtocolOptions; window.showSettings = showSettings; window.saveSettings = saveSettings;