Update to reply functionality and profile creation along with everything else. #2

Closed
ciajaf wants to merge 4 commits from ciajaf/super_ball:master into master
Showing only changes of commit 59b0461bad - Show all commits

View File

@@ -32,18 +32,19 @@
<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="nevent">Nevent:</label> <label for="reply-id">EventId/NoteId/Nevent:</label>
<textarea id="nevent" placeholder="Enter the nevent for the note..."></textarea> <textarea id="reply-id" placeholder="Enter the nevent for the note..."></textarea>
<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>
@@ -67,6 +68,16 @@
<label for="lud16">Lightning Address:</label> <label for="lud16">Lightning Address:</label>
<textarea id="lud16" placeholder="Enter your lightning address..."></textarea> <textarea id="lud16" placeholder="Enter your lightning address..."></textarea>
</div> </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>
<button onclick="createFinalEvent()">Create Event That Will Be Published Publicly</button> <button onclick="createFinalEvent()">Create Event That Will Be Published Publicly</button>
@@ -107,12 +118,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>
@@ -770,6 +781,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
@@ -777,8 +861,9 @@
// Get content based on active tab // Get content based on active tab
let content = ''; let content = '';
let nevent = ''; let replyEventId = '';
let neventData; let replyEvent = {};
let replyTags = [];
let name = ''; let name = '';
let about = ''; let about = '';
let profilePic = ''; let profilePic = '';
@@ -787,14 +872,16 @@
let banner = ''; let banner = '';
let nip05 = ''; let nip05 = '';
let lud16 = ''; 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();
nevent = document.getElementById('nevent').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();
@@ -806,6 +893,11 @@
nip05 = document.getElementById('nip05').value.trim(); nip05 = document.getElementById('nip05').value.trim();
lud16 = document.getElementById('lud16').value.trim(); lud16 = document.getElementById('lud16').value.trim();
break; break;
case 'tab4': // Custom Event
kind = document.getElementById('kind').value.trim();
content = document.getElementById('content').value.trim();
tags = document.getElementById('tags').value.trim();
break;
} }
// Validate content based on tab // Validate content based on tab
@@ -819,14 +911,33 @@
alert('Please enter message content'); alert('Please enter message content');
return; return;
} }
if (!nevent.startsWith('nevent')) { let eventId = '';
alert('Please enter a valid nevent'); 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; return;
} }
const regex = /^[0-9a-f]{64}$/;
if (!regex.test(eventId)) {
alert('Invalid event ID');
}
try { try {
neventData = window.NostrTools.nip19.decode(nevent).data; [ replyEvent, replyTags ] = await loadReplyTagsForEvent(eventId, knownRelays);
} catch (error) { } catch (error) {
alert('Error decoding nevent string', error.message); alert('Error fetching reply event', error.message);
return; return;
} }
} else if (activeTab === 'tab3') { } else if (activeTab === 'tab3') {
@@ -834,6 +945,22 @@
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 {
@@ -853,12 +980,9 @@
eventTemplate = { eventTemplate = {
kind: 1, kind: 1,
content: content, content: content,
tags: [['e', neventData.id, neventData.relays[0], 'root'], ['p', neventData.author]], tags: replyTags,
created_at: Math.floor(Date.now() / 1000) created_at: Math.floor(Date.now() / 1000)
}; };
neventData.relays.slice(1).forEach(relay => {
eventTemplate.tags.push(['r', relay]);
});
break; break;
case 'tab3': // Create Profile case 'tab3': // Create Profile
@@ -878,6 +1002,15 @@
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
@@ -2084,7 +2217,7 @@
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('bounces-container').innerHTML = ''; document.getElementById('bounces-container').innerHTML = '';