NIP-28 support!

This commit is contained in:
pablof7z 2023-06-05 23:50:16 +02:00
parent 842a0d4703
commit 053a1c8ed2
15 changed files with 906 additions and 22309 deletions

View file

@ -12,8 +12,8 @@
renter a Svelte component upon loading this page.</p> renter a Svelte component upon loading this page.</p>
<script src="public/bundle.js" <script src="public/bundle.js"
data-chat-type="GLOBAL" data-chat-type="NIP-28"
data-chat-tags="nostrica,nostrica2023" data-chat-id="a6f436a59fdb5e23c757b1e30478742996c54413df777843e0a731af56a96eea"
data-relays="wss://relay.nostrica.com,wss://relay.f7z.io,wss://nos.lol,wss://relay.nostr.info,wss://nostr-pub.wellorder.net,wss://relay.current.fyi,wss://relay.nostr.band" data-relays="wss://relay.nostrica.com,wss://relay.f7z.io,wss://nos.lol,wss://relay.nostr.info,wss://nostr-pub.wellorder.net,wss://relay.current.fyi,wss://relay.nostr.band"
></script> ></script>

876
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{ {
"name": "nostri.chat", "name": "nostri.chat",
"version": "0.1.5", "version": "0.3.14159",
"scripts": { "scripts": {
"dev": "vite dev", "dev": "vite dev",
"build": "svelte-kit sync && svelte-package", "build": "svelte-kit sync && svelte-package",
@ -11,13 +11,14 @@
"@sveltejs/adapter-auto": "^1.0.0", "@sveltejs/adapter-auto": "^1.0.0",
"@sveltejs/kit": "^1.0.0", "@sveltejs/kit": "^1.0.0",
"@sveltejs/package": "^1.0.0", "@sveltejs/package": "^1.0.0",
"autoprefixer": "^10.4.13", "autoprefixer": "^10.4.14",
"debug": "^4.3.4", "debug": "^4.3.4",
"postcss": "^8.4.21", "postcss": "^8.4.21",
"rollup-plugin-svelte": "^7.1.0", "rollup-plugin-polyfill-node": "^0.12.0",
"rollup-plugin-svelte": "^7.1.5",
"sirv-cli": "^2.0.2", "sirv-cli": "^2.0.2",
"svelte": "^3.54.0", "svelte": "^3.54.0",
"tailwindcss": "^3.2.4", "tailwindcss": "^3.3.2",
"tslib": "^2.4.1", "tslib": "^2.4.1",
"typescript": "^4.9.3", "typescript": "^4.9.3",
"vite": "^4.0.0" "vite": "^4.0.0"
@ -26,9 +27,10 @@
"dependencies": { "dependencies": {
"@nostr-connect/connect": "^0.2.3", "@nostr-connect/connect": "^0.2.3",
"@nostr-dev-kit/ndk": "^0.3.32", "@nostr-dev-kit/ndk": "^0.3.32",
"@rollup/plugin-alias": "^5.0.0",
"@rollup/plugin-commonjs": "^24.0.1", "@rollup/plugin-commonjs": "^24.0.1",
"@rollup/plugin-json": "^6.0.0", "@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-typescript": "^11.0.0", "@rollup/plugin-typescript": "^11.1.1",
"@sveltejs/adapter-node": "^1.1.7", "@sveltejs/adapter-node": "^1.1.7",
"@tailwindcss/forms": "^0.5.3", "@tailwindcss/forms": "^0.5.3",
"@tailwindcss/typography": "^0.5.9", "@tailwindcss/typography": "^0.5.9",

View file

@ -3,6 +3,7 @@ import sveltePreprocess from "svelte-preprocess";
import { vitePreprocess } from '@sveltejs/kit/vite'; import { vitePreprocess } from '@sveltejs/kit/vite';
import tailwindcss from "tailwindcss"; import tailwindcss from "tailwindcss";
import autoprefixer from "autoprefixer"; import autoprefixer from "autoprefixer";
import nodePolyfills from 'rollup-plugin-polyfill-node';
import resolve from "@rollup/plugin-node-resolve"; import resolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs"; import commonjs from "@rollup/plugin-commonjs";
import css from "rollup-plugin-css-only"; import css from "rollup-plugin-css-only";
@ -22,6 +23,12 @@ export default {
format: "iife", format: "iife",
name: "app", name: "app",
sourcemap: production, sourcemap: production,
globals: {
"https": "https",
"http": "http",
"net": "net",
}
}, },
plugins: [ plugins: [
// compile svelte with tailwindcss as preprocess (including autoprefixer) // compile svelte with tailwindcss as preprocess (including autoprefixer)
@ -45,6 +52,7 @@ export default {
}), }),
json(), json(),
commonjs(), commonjs(),
nodePolyfills( /* options */ ),
// export CSS in separate file for better performance // export CSS in separate file for better performance
css({ output: "bundle.css" }), css({ output: "bundle.css" }),
@ -64,6 +72,6 @@ export default {
!production && livereload("public/"), !production && livereload("public/"),
// minify bundles in production mode // minify bundles in production mode
// production && terser(), production && terser(),
], ],
}; };

View file

@ -14,8 +14,12 @@
let prevChatConfiguration; let prevChatConfiguration;
$: { $: {
if (chatConfiguration !== prevChatConfiguration && prevChatConfiguration && $chatAdapter) { if (chatConfiguration !== prevChatConfiguration && $chatAdapter) {
$chatAdapter.setChatConfiguration(chatConfiguration.chatType, chatConfiguration.chatTags, chatConfiguration.chatReferenceTags); $chatAdapter.setChatConfiguration(
chatConfiguration.chatType,
chatConfiguration.chatTags,
chatConfiguration.chatReferenceTags,
chatConfiguration.chatId);
events = []; events = [];
responses = {}; responses = {};
rootNoteId = null; rootNoteId = null;
@ -46,7 +50,7 @@
// if we are responding to an event, we want to tag the event and the pubkey // if we are responding to an event, we want to tag the event and the pubkey
if ($selectedMessage) { if ($selectedMessage) {
extraParams.tags.push(['e', $selectedMessage]); extraParams.tags.push(['e', $selectedMessage, "wss://nos.lol", "root"]);
extraParams.tagPubKeys.push(getEventById($selectedMessage).pubkey); extraParams.tagPubKeys.push(getEventById($selectedMessage).pubkey);
} }
@ -86,6 +90,8 @@
if (chatConfiguration.chatType === 'GLOBAL') { if (chatConfiguration.chatType === 'GLOBAL') {
isThread = message.tags.filter(tag => tag[0] === 'e').length >= 1; isThread = message.tags.filter(tag => tag[0] === 'e').length >= 1;
} else if (chatConfiguration.chatType === 'GROUP') {
isThread = message.tags.filter(tag => tag[0] === 'e' && tag[1] !== chatConfiguration.chatId).length >= 1;
} else { } else {
const pubkeysTagged = message.tags.filter(tag => tag[0] === 'p').map(tag => tag[1]); const pubkeysTagged = message.tags.filter(tag => tag[0] === 'p').map(tag => tag[1]);
isThread = new Set(pubkeysTagged).size >= 2; isThread = new Set(pubkeysTagged).size >= 2;
@ -147,6 +153,7 @@
} }
let rootNoteId; let rootNoteId;
let channelMetadata = {};
onMount(() => { onMount(() => {
$chatAdapter.on('message', messageReceived); $chatAdapter.on('message', messageReceived);
@ -173,6 +180,10 @@
chatData.set({ profiles, ...$chatData }) chatData.set({ profiles, ...$chatData })
}) })
$chatAdapter.on('channelMetadata', (event) => {
channelMetadata = JSON.parse(event.content);
})
}); });
let connectivityStatus = {}; let connectivityStatus = {};
@ -188,14 +199,25 @@
} }
} }
let connectedChatId;
$: if (connectedChatId !== $chatAdapter?.chatId) {
connectedChatId = $chatAdapter?.chatId;
channelMetadata = {};
}
$: profiles = $chatData.profiles; $: profiles = $chatData.profiles;
function selectParent() { function selectParent() {
// get the last tagged event in the tags array of the current $selectedMessage if (chatConfiguration.chatType === 'GROUP') {
const lastETag = getEventById($selectedMessage).tags.filter(tag => tag[0] === 'e').pop(); $selectedMessage = null;
const lastETagId = lastETag && lastETag[1]; } else {
// get the last tagged event in the tags array of the current $selectedMessage
const lastETag = getEventById($selectedMessage).tags.filter(tag => tag[0] === 'e').pop();
const lastETagId = lastETag && lastETag[1];
$selectedMessage = lastETagId; $selectedMessage = lastETagId;
}
scrollDown() scrollDown()
} }
@ -254,6 +276,21 @@
</span> </span>
</div> </div>
{#if channelMetadata.name}
<div class="flex flex-row gap-2 mb-3 bg-zinc-300 text-zinc-800 px-4 py-2 -mx-4 -mt-3">
{#if channelMetadata.picture}
<img src={channelMetadata.picture} class="w-12 h-12 rounded-full" />
{/if}
<div class="flex flex-col">
<div class="font-extrabold text-xl">{channelMetadata.name}</div>
{#if channelMetadata.about}
<div class="text-sm truncate font-regular">{channelMetadata.about}</div>
{/if}
</div>
</div>
{/if}
{#if $selectedMessage} {#if $selectedMessage}
{#if !getEventById($selectedMessage)} {#if !getEventById($selectedMessage)}
<h1>Couldn't find event with ID {$selectedMessage}</h1> <h1>Couldn't find event with ID {$selectedMessage}</h1>
@ -299,9 +336,12 @@
{#if chatConfiguration.chatType === 'DM'} {#if chatConfiguration.chatType === 'DM'}
<b>Encrypted chat:</b> <b>Encrypted chat:</b>
only your chat partner can see these messages. only your chat partner can see these messages.
{:else} {:else if chatConfiguration.chatType === 'GROUP'}
<b>Public chat:</b> <b>Public chat:</b>
anyone can see these messages. anyone can see these messages.
{:else}
<b>Public notes:</b>
your followers see your messages on their timeline
{/if} {/if}
</div> </div>

View file

@ -1,6 +1,6 @@
<script> <script>
import { onMount } from "svelte"; import { onMount } from "svelte";
import QR from 'svelte-qr'; // import QR from 'svelte-qr';
import { chatAdapter } from './lib/store'; import { chatAdapter } from './lib/store';
import NstrAdapterNip07 from './lib/adapters/nip07.js'; import NstrAdapterNip07 from './lib/adapters/nip07.js';
import NstrAdapterNip46 from './lib/adapters/nip46.js'; import NstrAdapterNip46 from './lib/adapters/nip46.js';
@ -66,7 +66,7 @@
localStorage.setItem('nostrichat-nostr-connect-key', key); localStorage.setItem('nostrichat-nostr-connect-key', key);
localStorage.setItem('nostrichat-nostr-connect-public-key', connectedPubKey); localStorage.setItem('nostrichat-nostr-connect-public-key', connectedPubKey);
localStorage.setItem('nostrichat-type', 'nip-46'); localStorage.setItem('nostrichat-type', 'nip-46');
console.log('connected to nostr connect relay') console.log('connected to nostr connect relay')
publicKey = connectedPubKey; publicKey = connectedPubKey;
chatAdapter.set(new NstrAdapterNip46(publicKey, key)) chatAdapter.set(new NstrAdapterNip46(publicKey, key))
@ -128,7 +128,7 @@
<div class="bg-white w-full p-3" <div class="bg-white w-full p-3"
on:click|preventDefault={Nip46Copy}> on:click|preventDefault={Nip46Copy}>
<QR text={nip46URI} /> <!-- <QR text={nip46URI} /> -->
</div> </div>
<button class=" <button class="

View file

@ -29,7 +29,7 @@
// delay-fetch responses // delay-fetch responses
onMount(() => { onMount(() => {
$chatAdapter.delayedSubscribe( $chatAdapter.delayedSubscribe(
{kinds: [1, 9735], '#e': [event.id]} {kinds: [1, 42, 9735], '#e': [event.id]}
, 'responses', 500) , 'responses', 500)
}) })
@ -100,7 +100,7 @@
<p class="flex flex-col items-center my-4"> <p class="flex flex-col items-center my-4">
⚡️ ⚡️
<span class="text-orange-500 font-semibold"> <span class="text-orange-500 font-semibold">
{zappedAmount} {zappedAmount/1000}
</span> </span>
</p> </p>
{:else} {:else}

View file

@ -6,9 +6,9 @@
export let chatTags; export let chatTags;
export let chatReferenceTags; export let chatReferenceTags;
export let relays; export let relays;
export let chatId;
let showChat = false; let showChat = false;
let dismissedIntro = true;
let minimizeChat = false; let minimizeChat = false;
function toggleChat() { function toggleChat() {
@ -18,10 +18,6 @@
showChat = !showChat; showChat = !showChat;
} }
} }
function dismissIntro() {
dismissedIntro = true;
}
</script> </script>
<div class=" <div class="
@ -35,63 +31,16 @@
flex flex-col justify-end flex flex-col justify-end
{minimizeChat ? 'hidden' : ''} {minimizeChat ? 'hidden' : ''}
" style="max-height: 80vh;"> " style="max-height: 80vh;">
{#if !dismissedIntro} <Container
<h1 class=" {websiteOwnerPubkey}
font-bold chatConfiguration={{
text-2xl chatType,
text-purple-700"> chatTags,
NostriChat chatId,
</h1> chatReferenceTags,
}}
<p class="text-gray-700 mb-3"> {relays}
This is a FOSS chat app built on top of the Nostr protocol. />
</p>
<p class="text-gray-700 mb-3">
Choose how you would like to chat:
</p>
<p class="text-gray-700 mb-3">
You can use it to ask for help
<span class="font-bold">PSBT.io</span>
to the creators of this site or to
anyone willing to help.
</p>
<p class="text-gray-700 mb-3">
Keep in mind that this chat is public,
anyone can read it, so don't exchange
private information and use common-sense.
</p>
<button class="
bg-purple-900
hover:bg-purple-700
w-full
p-2
py-4
text-xl
mt-3
rounded-xl
text-center
font-semibold
tracking-wide
uppercase
text-white
" on:click={dismissIntro}>
Continue
</button>
{:else}
<Container
{websiteOwnerPubkey}
chatConfiguration={{
chatType,
chatTags,
chatReferenceTags,
}}
{relays}
/>
{/if}
</div> </div>
{/if} {/if}

View file

@ -21,6 +21,7 @@ class NstrAdapter {
referenceTags; referenceTags;
type; type;
#websiteOwnerPubkey; #websiteOwnerPubkey;
chatId;
relayUrls = []; relayUrls = [];
#profileRequestQueue = []; #profileRequestQueue = [];
@ -29,25 +30,24 @@ class NstrAdapter {
#delayedSubscriptions = {}; #delayedSubscriptions = {};
#delayedSubscriptionTimeouts = {}; #delayedSubscriptionTimeouts = {};
constructor(clientPubkey, {tags, referenceTags, type='DM', websiteOwnerPubkey, relays} = {}) { constructor(clientPubkey, {tags, referenceTags, type='DM', chatId, websiteOwnerPubkey, relays} = {}) {
this.pubkey = clientPubkey; this.pubkey = clientPubkey;
this.#websiteOwnerPubkey = websiteOwnerPubkey; this.#websiteOwnerPubkey = websiteOwnerPubkey;
this.relayUrls = relays this.relayUrls = relays
if (type) { if (type) {
this.setChatConfiguration(type, tags, referenceTags); this.setChatConfiguration(type, tags, referenceTags, chatId);
} }
} }
setChatConfiguration(type, tags, referenceTags) { setChatConfiguration(type, tags, referenceTags, chatId) {
log('chatConfiguration', {type, tags, referenceTags});
this.type = type; this.type = type;
this.tags = tags; this.tags = tags;
this.chatId = chatId;
this.referenceTags = referenceTags; this.referenceTags = referenceTags;
// handle connection // handle connection
if (this.#pool) { this.#disconnect() } if (this.#pool) { this.#disconnect() }
this.#connect()
let filters = []; let filters = [];
@ -61,6 +61,14 @@ class NstrAdapter {
'authors': [this.pubkey, this.#websiteOwnerPubkey] 'authors': [this.pubkey, this.#websiteOwnerPubkey]
}); });
break; break;
case 'GROUP':
if (this.chatId) {
filters.push({
kinds: [41, 42],
"#e": [this.chatId],
limit: 200,
})
}
case 'GLOBAL': case 'GLOBAL':
if (this.tags && this.tags.length > 0) { if (this.tags && this.tags.length > 0) {
filters.push({kinds: [1], '#t': this.tags, limit: 20}); filters.push({kinds: [1], '#t': this.tags, limit: 20});
@ -73,6 +81,7 @@ class NstrAdapter {
} }
if (filters && filters.length > 0) { if (filters && filters.length > 0) {
this.#connect()
this.subscribe(filters, (e) => { this.#emitMessage(e) }) this.subscribe(filters, (e) => { this.#emitMessage(e) })
} }
} }
@ -96,6 +105,8 @@ class NstrAdapter {
if (this.type === 'DM') { if (this.type === 'DM') {
event = await this.sendKind4(message, {tagPubKeys, tags}); event = await this.sendKind4(message, {tagPubKeys, tags});
} else if (this.type === 'GROUP') {
event = await this.sendKind42(message, {tagPubKeys, tags, chatId: this.chatId});
} else { } else {
event = await this.sendKind1(message, {tagPubKeys, tags}); event = await this.sendKind1(message, {tagPubKeys, tags});
} }
@ -124,6 +135,46 @@ class NstrAdapter {
return event; return event;
} }
async sendKind42(message, {tagPubKeys, tags, chatId} = {}) {
if (!tags) { tags = []; }
if (this.tags) {
this.tags.forEach((t) => tags.push(['t', t]));
}
// check if there is an e tag
const reply = !!tags.find((t) => t[0] === 'e');
if (!reply) {
tags.push(['e', chatId, "wss://nos.lol", reply ? "reply" : "root"]);
}
if (this.referenceTags) {
this.referenceTags.forEach((t) => tags.push(['r', t]));
}
let event = {
kind: 42,
created_at: Math.floor(Date.now() / 1000),
tags,
content: message,
pubkey: this.pubkey,
}
if (tagPubKeys) {
for (let pubkey of tagPubKeys) {
if (pubkey) {
event.tags.push(['p', pubkey]);
}
}
}
event.id = getEventHash(event)
this.subscribeToEventAndResponses(event.id);
return event;
}
async sendKind1(message, {tagPubKeys, tags} = {}) { async sendKind1(message, {tagPubKeys, tags} = {}) {
if (!tags) { tags = []; } if (!tags) { tags = []; }
@ -191,8 +242,6 @@ class NstrAdapter {
return groups; return groups;
}, groups); }, groups);
console.log(`turned ${filters.length} filters into ${groups.length} groups`);
groups.forEach((filters) => { groups.forEach((filters) => {
this.subscribe(filters, (e) => { this.#emitMessage(e)}); this.subscribe(filters, (e) => { this.#emitMessage(e)});
}); });
@ -246,7 +295,11 @@ class NstrAdapter {
} }
switch (event.kind) { switch (event.kind) {
case 1: this.#eventEmitter.emit('message', event); break; case 1:
case 42:
this.#eventEmitter.emit('message', event); break;
case 41:
this.#eventEmitter.emit('channelMetadata', event); break;
case 4: this.#eventEmitter.emit('message', event); break; case 4: this.#eventEmitter.emit('message', event); break;
case 5: this.#eventEmitter.emit('deleted', deletedEvents); break; case 5: this.#eventEmitter.emit('deleted', deletedEvents); break;
case 7: this.#eventEmitter.emit('reaction', event); break; case 7: this.#eventEmitter.emit('reaction', event); break;

View file

@ -2,19 +2,17 @@
import 'websocket-polyfill'; import 'websocket-polyfill';
import Container from '../Container.svelte'; import Container from '../Container.svelte';
import Widget from '../Widget.svelte'; import Widget from '../Widget.svelte';
import { chatAdapter } from '$lib/store'; import { chatAdapter } from '../lib/store';
let chatStarted; let chatStarted;
let chatType = 'GLOBAL'; let chatType = 'GROUP';
let websiteOwnerPubkey = 'fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52'; let websiteOwnerPubkey = 'fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52';
let chatTags = ['bitcoin']; let chatTags = [];
let chatId = '9cef2eead5d91df42eba09be363f1272107e911685126ea5e261ac2d93299478';
let chatReferenceTags = []; let chatReferenceTags = [];
const relays = [ const relays = [
'wss://relay.f7z.io', 'wss://relay.f7z.io',
'wss://relay.nostr.info', 'wss://nos.lol',
'wss://nostr-pub.wellorder.net',
'wss://relay.nos.lol',
'wss://nostr.walletofsatoshi.com',
'wss://relay.nostr.band', 'wss://relay.nostr.band',
]; ];
@ -87,6 +85,7 @@
" style="{chatStarted ? 'max-height: 80vh;' : 'padding: 4rem 2rem !important;'}"> " style="{chatStarted ? 'max-height: 80vh;' : 'padding: 4rem 2rem !important;'}">
<Container chatConfiguration={{ <Container chatConfiguration={{
chatType, chatType,
chatId,
chatTags, chatTags,
chatReferenceTags, chatReferenceTags,
}} {relays} bind:chatStarted={chatStarted} /> }} {relays} bind:chatStarted={chatStarted} />
@ -148,6 +147,60 @@
</div> </div>
<div class="flex flex-col gap-3"> <div class="flex flex-col gap-3">
<h2 class="text-3xl text-orange-600 font-black">
<div class="flex flex-row gap-2">
<span>🫂</span>
<span class="flex flex-col">
<span>Public chat groups</span>
<span class="text-2xl text-slate-500 font-extralight block">public groups</span>
</span>
</div>
</h2>
<p class="
text-xl text-gray-500 text-justify
font-light
leading-8
">
Embed NIP-28 public chat groups on your site.
</p>
<div class="flex flex-col lg:flex-row justify-between mt-10 gap-10 mb-6">
<div class="flex flex-col lg:w-1/2 items-center gap-4 border p-4 shadow-md rounded-lg w-fit">
<h3 class="
text-black
text-lg
font-semibold
">Group chat</h3>
<span class="inline-flex rounded-md">
<button type="button" class="
inline-flex items-center rounded-l-md border px-4 py-2 text-md font-medium
{chatType === 'GROUP' && chatId === '9cef2eead5d91df42eba09be363f1272107e911685126ea5e261ac2d93299478' ?
'text-white bg-orange-700 border-orange-900'
:
'border-gray-300 bg-white text-gray-700'}
:ring-indigo-500"
on:click={()=>{ chatType='GROUP'; chatTags=[]; chatId='9cef2eead5d91df42eba09be363f1272107e911685126ea5e261ac2d93299478' }}
>
#Test
</button>
<button type="button" class="
inline-flex items-center rounded-r-md border px-4 py-2 text-md font-medium
{chatType === 'GROUP' && chatId === 'a6f436a59fdb5e23c757b1e30478742996c54413df777843e0a731af56a96eea' ?
'text-white bg-orange-700 border-orange-900'
:
'border-gray-300 bg-white text-gray-700'}
:ring-indigo-500"
on:click={()=>{ chatType='GROUP'; chatTags=[]; chatId='a6f436a59fdb5e23c757b1e30478742996c54413df777843e0a731af56a96eea' }}
>
#NDK
</button>
</span>
</div>
</div>
<h2 class="text-3xl text-orange-600 font-black"> <h2 class="text-3xl text-orange-600 font-black">
<div class="flex flex-row gap-2"> <div class="flex flex-row gap-2">
<span>🔖</span> <span>🔖</span>
@ -156,8 +209,6 @@
<span class="text-2xl text-slate-500 font-extralight block">public discussion/support</span> <span class="text-2xl text-slate-500 font-extralight block">public discussion/support</span>
</span> </span>
</div> </div>
</h2> </h2>
<p class=" <p class="
@ -262,6 +313,7 @@
</p> </p>
</div> </div>
<div class="text-xl font-semibold">Public group chat (GROUP)</div>
<pre class =" <pre class ="
p-4 p-4
bg-white bg-white
@ -269,14 +321,37 @@
"> ">
&lt;script &lt;script
src="https://nostri.chat/public/bundle.js" src="https://nostri.chat/public/bundle.js"
<span class="text-green-600">// YOUR PUBKEY IN HEX FORMAT</span> <b>data-chat-type</b>="<span class="text-orange-500">GROUP</span>"
<b>data-website-owner-pubkey</b>="<span class="text-orange-500">YOUR_PUBKEY"</span> <b>data-chat-id</b>="<span class="text-orange-500">&lt;GROUP_ID_IN_HEX_FORMAT&gt;</span>"
<span class="text-green-600">// THE TYPE OF CHAT YOU WANT: GLOBAL or DMs</span> <b>data-relays</b>="<span class="text-orange-500">wss://relay.f7z.io,wss://nos.lol,wss://relay.nostr.band</span>"
<b>data-chat-type</b>="<span class="text-orange-500">GLOBAL" </span> &gt;&lt;/script&gt;
<span class="text-green-600">// If you use GLOBAL you can choose set a comma-separated list of hashtags</span> &lt;link rel="stylesheet" href="https://nostri.chat/public/bundle.css"&gt;</pre>
<b>data-chat-tags</b>="<span class="text-orange-500">nostrica,bitcoin"</span>
<span class="text-green-600">// Relays you'd like to use, change this this as you wish</span> <div class="text-xl font-semibold">Public global notes (kind-1 short notes)</div>
<b>data-relays</b>="<span class="text-orange-500">wss://relay.f7z.io,wss://nos.lol,wss://relay.nostr.info,wss://nostr-pub.wellorder.net,wss://relay.current.fyi,wss://relay.nostr.band"</span> <pre class ="
p-4
bg-white
overflow-auto
">
&lt;script
src="https://nostri.chat/public/bundle.js"
<b>data-chat-type</b>="<span class="text-orange-500">GLOBAL</span>"
<b>data-chat-tags</b>="<span class="text-orange-500">bitcoin</span>"
<b>data-relays</b>="<span class="text-orange-500">wss://relay.f7z.io,wss://nos.lol,wss://relay.nostr.band</span>"
&gt;&lt;/script&gt;
&lt;link rel="stylesheet" href="https://nostri.chat/public/bundle.css"&gt;</pre>
<div class="text-xl font-semibold">Encrypted DMs</div>
<pre class ="
p-4
bg-white
overflow-auto
">
&lt;script
src="https://nostri.chat/public/bundle.js"
<b>data-chat-type</b>="<span class="text-orange-500">DM</span>"
<b>data-website-owner-pubkey</b>="<span class="text-orange-500">YOUR_PUBKEY_IN_HEX_FORMAT</span>"
<b>data-relays</b>="<span class="text-orange-500">wss://relay.f7z.io,wss://nos.lol,wss://relay.nostr.band</span>"
&gt;&lt;/script&gt; &gt;&lt;/script&gt;
&lt;link rel="stylesheet" href="https://nostri.chat/public/bundle.css"&gt;</pre> &lt;link rel="stylesheet" href="https://nostri.chat/public/bundle.css"&gt;</pre>
</div> </div>
@ -285,10 +360,9 @@
<div class="md:hidden"> <div class="md:hidden">
<Widget chatConfiguration={{ <Widget chatConfiguration={{
chatType,
chatTags, chatTags,
chatReferenceTags, chatReferenceTags,
}} {websiteOwnerPubkey} {relays} bind:chatStarted={chatStarted} /> }} {websiteOwnerPubkey} {chatType} {chatId} {relays} bind:chatStarted={chatStarted} />
</div> </div>
<footer class="py-6 bg-orange-900 font-mono text-white text-center mt-12 px-10"> <footer class="py-6 bg-orange-900 font-mono text-white text-center mt-12 px-10">

View file

@ -14,8 +14,8 @@
<script <script
src="/public/bundle.js" src="/public/bundle.js"
data-website-owner-pubkey="fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52" data-website-owner-pubkey="fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52"
data-chat-type="GLOBAL" data-chat-type="GROUP"
data-chat-tags="nostrica" data-chat-id="a6f436a59fdb5e23c757b1e30478742996c54413df777843e0a731af56a96eea"
data-relays="wss://relay.f7z.io,wss://nos.lol,wss://relay.nostr.info,wss://nostr-pub.wellorder.net,wss://relay.current.fyi,wss://relay.nostr.band" data-relays="wss://relay.f7z.io,wss://nos.lol,wss://relay.nostr.info,wss://nostr-pub.wellorder.net,wss://relay.current.fyi,wss://relay.nostr.band"
></script> ></script>

View file

@ -5,6 +5,7 @@ var script = document.currentScript;
const websiteOwnerPubkey = script.getAttribute('data-website-owner-pubkey'); const websiteOwnerPubkey = script.getAttribute('data-website-owner-pubkey');
const chatType = script.getAttribute('data-chat-type'); const chatType = script.getAttribute('data-chat-type');
let chatTags = script.getAttribute('data-chat-tags'); let chatTags = script.getAttribute('data-chat-tags');
let chatId = script.getAttribute('data-chat-id');
let chatReferenceTags = script.getAttribute('data-chat-reference-tags'); let chatReferenceTags = script.getAttribute('data-chat-reference-tags');
let relays = script.getAttribute('data-relays'); let relays = script.getAttribute('data-relays');
script.parentNode.insertBefore(div, script); script.parentNode.insertBefore(div, script);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long