forked from laantungir/super_ball
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 58e2ae95c0 | |||
| 792eb46ca2 | |||
| ee5f318532 | |||
| 59b0461bad | |||
| 9285f8e583 | |||
| c5ec067a79 | |||
| 387f5d4725 |
@@ -142,7 +142,8 @@ button:active {
|
|||||||
label {
|
label {
|
||||||
display: block;
|
display: block;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-bottom: 3px;
|
margin-bottom: 2px;
|
||||||
|
margin-top: 7px;
|
||||||
font-family: var(--font-family);
|
font-family: var(--font-family);
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
}
|
}
|
||||||
@@ -744,11 +745,6 @@ small {
|
|||||||
margin: 20px;
|
margin: 20px;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
label {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -789,3 +785,19 @@ textarea {
|
|||||||
.tab-content.active {
|
.tab-content.active {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fetched-event {
|
||||||
|
background: var(--secondary-color);
|
||||||
|
border: 1px solid var(--muted-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 10px;
|
||||||
|
font-family: var(--font-family);
|
||||||
|
font-size: 16px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
margin: 10px 0;
|
||||||
|
color: var(--primary-color);
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,24 +27,26 @@
|
|||||||
|
|
||||||
<!-- FINAL EVENT SECTION -->
|
<!-- FINAL EVENT SECTION -->
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2>Final Event (What gets posted at the end)</h2>
|
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<div class="tab active" data-tab="tab1">Post</div>
|
<div class="tab active" data-tab="tab1">Post</div>
|
||||||
<div class="tab" data-tab="tab2">Reply</div>
|
<div class="tab" data-tab="tab2">Reply</div>
|
||||||
<div class="tab" data-tab="tab3">Create Profile</div>
|
<div class="tab" data-tab="tab3">Create/Edit Profile</div>
|
||||||
|
<div class="tab" data-tab="tab4">Custom Event</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-content active" id="tab1">
|
<div class="tab-content active" id="tab1">
|
||||||
<h3>Post</h3>
|
<h3>Post</h3>
|
||||||
<label for="final-content">Message Content:</label>
|
<label for="post-content">Message Content:</label>
|
||||||
<textarea id="final-content" rows="3" placeholder="Enter your message content..."></textarea>
|
<textarea id="post-content" rows="3" placeholder="Enter your message content..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-content" id="tab2">
|
<div class="tab-content" id="tab2">
|
||||||
<h3>Reply</h3>
|
<h3>Reply</h3>
|
||||||
<label for="reply-id">Replying To:</label>
|
<label for="reply-id">EventId/NoteId/Nevent:</label>
|
||||||
<textarea id="reply-id" placeholder="Enter the eventId..."></textarea>
|
<textarea id="reply-id" placeholder="Enter the nevent for the note..."></textarea>
|
||||||
|
|
||||||
|
<label for="fetched-event-display" id="fetched-event-label" style="display: none;">Event Replying To:</label>
|
||||||
|
<div id="fetched-event-display" class="fetched-event"></div>
|
||||||
<label for="reply-content">Message Content:</label>
|
<label for="reply-content">Message Content:</label>
|
||||||
<textarea id="reply-content" rows="3" placeholder="Enter your message content..."></textarea>
|
<textarea id="reply-content" rows="3" placeholder="Enter your message content..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
@@ -53,10 +55,35 @@
|
|||||||
<h3>Create Profile</h3>
|
<h3>Create Profile</h3>
|
||||||
<label for="name">Name:</label>
|
<label for="name">Name:</label>
|
||||||
<textarea id="name" placeholder="Enter your name..."></textarea>
|
<textarea id="name" placeholder="Enter your name..."></textarea>
|
||||||
|
<label for="about">About:</label>
|
||||||
|
<textarea id="about" rows="2" placeholder="A short bio..."></textarea>
|
||||||
|
<label for="profile-pic">Profile Picture:</label>
|
||||||
|
<textarea id="profile-pic" placeholder="URL of your profile pic..."></textarea>
|
||||||
|
<label for="display-name">Display Name:</label>
|
||||||
|
<textarea id="display-name" placeholder="Enter your display name..."></textarea>
|
||||||
|
<label for="website">Website:</label>
|
||||||
|
<textarea id="website" placeholder="Web URL..."></textarea>
|
||||||
|
<label for="banner">Banner:</label>
|
||||||
|
<textarea id="banner" placeholder="Enter your bannerm a (~1024x768) wide picture url..."></textarea>
|
||||||
|
<label for="nip05">NIP05:</label>
|
||||||
|
<textarea id="nip05" placeholder="Enter your nip05 in the format username@domain.com..."></textarea>
|
||||||
|
<label for="lud16">Lightning Address:</label>
|
||||||
|
<textarea id="lud16" placeholder="Enter your lightning address..."></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tab-content" id="tab4">
|
||||||
|
<h3>Custom Event</h3>
|
||||||
|
<label for="kind">Event Kind:</label>
|
||||||
|
<textarea id="kind" placeholder="Enter your event kind. Ex: 0, 1, 30000..."></textarea>
|
||||||
|
<label for="content">Content:</label>
|
||||||
|
<textarea id="content" rows="3" placeholder="A short bio..."></textarea>
|
||||||
|
<label for="tags">Tags:</label>
|
||||||
|
<textarea id="tags" rows="3" placeholder="Tags in format [['p', 'pubkey...'], ['e', 'event_id', wss://nos.lol, 'pubkey...']]"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button onclick="createFinalEvent()">Create Event That Will Be Published Publicly</button>
|
<button onclick="createFinalEvent()">Create Event That Will Be Published Publicly</button>
|
||||||
|
|
||||||
|
<h2 style="padding-top: 16px;">Final Event (What gets posted at the end)</h2>
|
||||||
<div id="final-event-display" class="json-display"></div>
|
<div id="final-event-display" class="json-display"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -94,12 +121,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Load the official nostr-tools bundle first -->
|
<!-- Load the official nostr-tools bundle first -->
|
||||||
<!-- <script src="./nostr.bundle.js"></script> -->
|
<script src="./nostr.bundle.js"></script>
|
||||||
<script src="https://laantungir.net/nostr-login-lite/nostr.bundle.js"></script>
|
<!-- <script src="https://laantungir.net/nostr-login-lite/nostr.bundle.js"></script> -->
|
||||||
|
|
||||||
<!-- Load NOSTR_LOGIN_LITE main library -->
|
<!-- Load NOSTR_LOGIN_LITE main library -->
|
||||||
<script src="https://laantungir.net/nostr-login-lite/nostr-lite.js"></script>
|
<!-- <script src="https://laantungir.net/nostr-login-lite/nostr-lite.js"></script> -->
|
||||||
<!-- <script src="./nostr-lite.js"></script> -->
|
<script src="./nostr-lite.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
@@ -233,6 +260,11 @@
|
|||||||
const name = profile.name || profile.display_name || profile.displayName || 'Anonymous User';
|
const name = profile.name || profile.display_name || profile.displayName || 'Anonymous User';
|
||||||
const about = profile.about || '';
|
const about = profile.about || '';
|
||||||
const picture = profile.picture || '';
|
const picture = profile.picture || '';
|
||||||
|
const display_name = profile.display_name || '';
|
||||||
|
const website = profile.website || '';
|
||||||
|
const banner = profile.banner || '';
|
||||||
|
const nip05 = profile.nip05 || '';
|
||||||
|
const lud16 = profile.lud16 || '';
|
||||||
|
|
||||||
document.getElementById('profile-name').textContent = name;
|
document.getElementById('profile-name').textContent = name;
|
||||||
|
|
||||||
@@ -240,6 +272,17 @@
|
|||||||
document.getElementById('profile-picture').src = picture;
|
document.getElementById('profile-picture').src = picture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Edit Profile section
|
||||||
|
|
||||||
|
document.getElementById('name').textContent = name;
|
||||||
|
document.getElementById('about').textContent = about;
|
||||||
|
document.getElementById('profile-pic').textContent = picture;
|
||||||
|
document.getElementById('display-name').textContent = display_name;
|
||||||
|
document.getElementById('website').textContent = website;
|
||||||
|
document.getElementById('banner').textContent = banner;
|
||||||
|
document.getElementById('nip05').textContent = nip05;
|
||||||
|
document.getElementById('lud16').textContent = lud16;
|
||||||
|
|
||||||
console.log('SUCCESS', `Profile displayed: ${name}`);
|
console.log('SUCCESS', `Profile displayed: ${name}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -757,6 +800,79 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load event from id
|
||||||
|
async function loadReplyTagsForEvent(id, knownRelays) {
|
||||||
|
if (!id) return;
|
||||||
|
|
||||||
|
console.log('INFO', `Loading event`, id);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const pool = new window.NostrTools.SimplePool();
|
||||||
|
const relays = [relayUrl, 'wss://relay.laantungir.net', 'wss://nos.lol', 'wss://relay.primal.net', 'wss://relay.damus.io', 'wss://relay.nostr.band'].concat(knownRelays);
|
||||||
|
|
||||||
|
// Enable tracking
|
||||||
|
pool.trackRelays = true;
|
||||||
|
|
||||||
|
// Query for an event
|
||||||
|
const events = await pool.querySync(relays, {
|
||||||
|
ids: [id],
|
||||||
|
limit: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
const event = events[0];
|
||||||
|
let returnEventTags = [];
|
||||||
|
let relaysSeenOn = [];
|
||||||
|
if (event) {
|
||||||
|
const seenRelays = pool.seenOn.get(event.id);
|
||||||
|
relaysSeenOn = seenRelays ? Array.from(seenRelays).map(r => r.url) : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
pool.close(relays);
|
||||||
|
|
||||||
|
if (events.length > 0) {
|
||||||
|
// event is a nostr event with tags
|
||||||
|
const refs = window.NostrTools.nip10.parse(events[0])
|
||||||
|
|
||||||
|
// get the root event of the thread
|
||||||
|
if (refs.root) {
|
||||||
|
const relay = refs.root.relays.length > 0 ? refs.root.relays[0] : '';
|
||||||
|
if (refs.root.author) {
|
||||||
|
returnEventTags.push(['e', refs.root.id, relay, 'root', refs.root.author]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
returnEventTags.push(['e', refs.root.id, relay, 'root']);
|
||||||
|
}
|
||||||
|
returnEventTags.push(['e', id, relaysSeenOn[0], 'reply', event.pubkey]);
|
||||||
|
if (refs.root.author)
|
||||||
|
returnEventTags.push(['p', refs.root.author, relay]);
|
||||||
|
returnEventTags.push(['p', event.pubkey, relaysSeenOn[0]]);
|
||||||
|
} else {
|
||||||
|
returnEventTags.push(['e', id, relaysSeenOn[0], 'root']);
|
||||||
|
returnEventTags.push(['p', event.pubkey]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get any referenced profiles
|
||||||
|
for (let profile of refs.profiles) {
|
||||||
|
if (!returnEventTags.some(tag => tag[0] === 'p' && tag[1] === profile.pubkey)) {
|
||||||
|
if (profile.relays.length > 0) {
|
||||||
|
returnEventTags.push(['p', profile.pubkey, profile.relays[0]]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
returnEventTags.push(['p', profile.pubkey]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [events[0], returnEventTags];
|
||||||
|
} else {
|
||||||
|
console.log('INFO', 'Event not found');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.log('ERROR', `Profile loading failed: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create final event (kind 1)
|
// Create final event (kind 1)
|
||||||
async function createFinalEvent() {
|
async function createFinalEvent() {
|
||||||
// Get the active tab
|
// Get the active tab
|
||||||
@@ -764,33 +880,112 @@
|
|||||||
|
|
||||||
// Get content based on active tab
|
// Get content based on active tab
|
||||||
let content = '';
|
let content = '';
|
||||||
let eventId = '';
|
let replyEventId = '';
|
||||||
|
let replyEvent = {};
|
||||||
|
let replyTags = [];
|
||||||
let name = '';
|
let name = '';
|
||||||
|
let about = '';
|
||||||
|
let profilePic = '';
|
||||||
|
let displayName = '';
|
||||||
|
let website = '';
|
||||||
|
let banner = '';
|
||||||
|
let nip05 = '';
|
||||||
|
let lud16 = '';
|
||||||
|
let tags = '';
|
||||||
|
let kind = '';
|
||||||
|
|
||||||
switch(activeTab) {
|
switch(activeTab) {
|
||||||
case 'tab1': // Post
|
case 'tab1': // Post
|
||||||
content = document.getElementById('final-content').value.trim();
|
content = document.getElementById('post-content').value.trim();
|
||||||
break;
|
break;
|
||||||
case 'tab2': // Reply
|
case 'tab2': // Reply
|
||||||
content = document.getElementById('reply-content').value.trim();
|
content = document.getElementById('reply-content').value.trim();
|
||||||
eventId = document.getElementById('reply-id').value.trim();
|
replyEventId = document.getElementById('reply-id').value.trim();
|
||||||
break;
|
break;
|
||||||
case 'tab3': // Create Profile
|
case 'tab3': // Create Profile
|
||||||
name = document.getElementById('name').value.trim();
|
name = document.getElementById('name').value.trim();
|
||||||
|
about = document.getElementById('about').value.trim();
|
||||||
|
profilePic = document.getElementById('profile-pic').value.trim();
|
||||||
|
displayName = document.getElementById('display-name').value.trim();
|
||||||
|
website = document.getElementById('website').value.trim();
|
||||||
|
banner = document.getElementById('banner').value.trim();
|
||||||
|
nip05 = document.getElementById('nip05').value.trim();
|
||||||
|
lud16 = document.getElementById('lud16').value.trim();
|
||||||
|
break;
|
||||||
|
case 'tab4': // Custom Event
|
||||||
|
kind = document.getElementById('kind').value.trim();
|
||||||
|
content = document.getElementById('content').value.trim();
|
||||||
|
tags = document.getElementById('tags').value.trim();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate content based on tab
|
// Validate content based on tab
|
||||||
if (activeTab === 'tab1' || activeTab === 'tab2') {
|
if (activeTab === 'tab1') {
|
||||||
if (!content) {
|
if (!content) {
|
||||||
alert('Please enter message content');
|
alert('Please enter message content');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else if (activeTab === 'tab2') {
|
||||||
|
if (!content) {
|
||||||
|
alert('Please enter message content');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let eventId = '';
|
||||||
|
let knownRelays = [];
|
||||||
|
try {
|
||||||
|
if (replyEventId.startsWith('nevent')) {
|
||||||
|
const replyEventData = window.NostrTools.nip19.decode(replyEventId).data;
|
||||||
|
eventId = replyEventData.id;
|
||||||
|
knownRelays = replyEventData.relays;
|
||||||
|
} else if (replyEventId.startsWith('note')) {
|
||||||
|
eventId = window.NostrTools.nip19.decode(replyEventId).data;
|
||||||
|
} else {
|
||||||
|
eventId = replyEventId;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
alert('Error decoding nevent string', error.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const regex = /^[0-9a-f]{64}$/;
|
||||||
|
if (!regex.test(eventId)) {
|
||||||
|
alert('Invalid event ID');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
document.getElementById('fetched-event-display').textContent = 'Loading event...';
|
||||||
|
document.getElementById('fetched-event-display').style.display = 'block';
|
||||||
|
document.getElementById('fetched-event-label').style.display = 'block';
|
||||||
|
[ replyEvent, replyTags ] = await loadReplyTagsForEvent(eventId, knownRelays);
|
||||||
|
console.log("Event replying to: ", replyEvent)
|
||||||
|
document.getElementById('fetched-event-display').textContent = replyEvent.content;
|
||||||
|
} catch (error) {
|
||||||
|
alert('Error fetching reply event', error.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else if (activeTab === 'tab3') {
|
} else if (activeTab === 'tab3') {
|
||||||
if (!name) {
|
if (!name) {
|
||||||
alert('Please enter your name');
|
alert('Please enter your name');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else if (activeTab === 'tab4') {
|
||||||
|
if (!kind) {
|
||||||
|
alert('Please enter the event kind');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!/^-?\d+$/.test(kind)) {
|
||||||
|
alert("Please enter a valid integer for event kind.");
|
||||||
|
return; // Prevent form submission
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
kind = Number(kind);
|
||||||
|
tags = JSON.parse(tags.replace(/'/g, '"'))
|
||||||
|
} catch (error) {
|
||||||
|
alert('Error parsing tags', error.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -810,7 +1005,7 @@
|
|||||||
eventTemplate = {
|
eventTemplate = {
|
||||||
kind: 1,
|
kind: 1,
|
||||||
content: content,
|
content: content,
|
||||||
tags: [['e', eventId, 'root']],
|
tags: replyTags,
|
||||||
created_at: Math.floor(Date.now() / 1000)
|
created_at: Math.floor(Date.now() / 1000)
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
@@ -819,17 +1014,34 @@
|
|||||||
eventTemplate = {
|
eventTemplate = {
|
||||||
kind: 0,
|
kind: 0,
|
||||||
content: JSON.stringify({
|
content: JSON.stringify({
|
||||||
name: name
|
name: name,
|
||||||
|
about: about,
|
||||||
|
picture: profilePic,
|
||||||
|
display_name: displayName,
|
||||||
|
website: website,
|
||||||
|
banner: banner,
|
||||||
|
nip05: nip05,
|
||||||
|
lud16: lud16
|
||||||
}),
|
}),
|
||||||
tags: [],
|
tags: [],
|
||||||
created_at: Math.floor(Date.now() / 1000)
|
created_at: Math.floor(Date.now() / 1000)
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'tab4': // Create Profile
|
||||||
|
eventTemplate = {
|
||||||
|
kind: kind,
|
||||||
|
content: content,
|
||||||
|
tags: tags,
|
||||||
|
created_at: Math.floor(Date.now() / 1000)
|
||||||
|
};
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Your existing event publishing logic here
|
// Your existing event publishing logic here
|
||||||
console.log('Event to publish:', eventTemplate);
|
console.log('Event to publish:', eventTemplate);
|
||||||
// ... rest of your publishing code
|
// ... rest of your publishing code
|
||||||
|
|
||||||
// Sign the event using window.nostr (NIP-07)
|
// Sign the event using window.nostr (NIP-07)
|
||||||
finalEvent = await window.nostr.signEvent(eventTemplate);
|
finalEvent = await window.nostr.signEvent(eventTemplate);
|
||||||
|
|
||||||
@@ -2030,8 +2242,11 @@
|
|||||||
bounceCounter = 0;
|
bounceCounter = 0;
|
||||||
|
|
||||||
// Clear UI elements
|
// Clear UI elements
|
||||||
document.getElementById('final-content').value = '';
|
document.getElementById('post-content').value = '';
|
||||||
document.getElementById('final-event-display').textContent = '';
|
document.getElementById('final-event-display').textContent = '';
|
||||||
|
document.getElementById('fetched-event-display').textContent = '';
|
||||||
|
document.getElementById('fetched-event-display').style.display = 'none';
|
||||||
|
document.getElementById('fetched-event-label').style.display = 'none';
|
||||||
document.getElementById('bounces-container').innerHTML = '';
|
document.getElementById('bounces-container').innerHTML = '';
|
||||||
|
|
||||||
// Hide the Add Bounce button since no final event exists
|
// Hide the Add Bounce button since no final event exists
|
||||||
|
|||||||
Reference in New Issue
Block a user