v0.3.7 - working on cinfig api
This commit is contained in:
286
api/index.html
286
api/index.html
@@ -1,5 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
@@ -10,7 +11,7 @@
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
font-family: 'Courier New', monospace;
|
||||
background-color: white;
|
||||
@@ -20,7 +21,7 @@
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
|
||||
h1 {
|
||||
border-bottom: 2px solid black;
|
||||
padding-bottom: 10px;
|
||||
@@ -28,7 +29,7 @@
|
||||
font-weight: normal;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
|
||||
h2 {
|
||||
margin: 30px 0 15px 0;
|
||||
font-weight: normal;
|
||||
@@ -36,25 +37,28 @@
|
||||
padding-left: 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
.section {
|
||||
border: 1px solid black;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
|
||||
.input-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
input, textarea, select, button {
|
||||
|
||||
input,
|
||||
textarea,
|
||||
select,
|
||||
button {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
border: 1px solid black;
|
||||
@@ -63,7 +67,7 @@
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
|
||||
button {
|
||||
background-color: black;
|
||||
color: white;
|
||||
@@ -71,65 +75,65 @@
|
||||
margin: 5px 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
button:hover {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
|
||||
button:disabled {
|
||||
background-color: #ccc;
|
||||
color: #666;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
|
||||
.status {
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
border: 1px solid black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.status.connected {
|
||||
background-color: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
.status.disconnected {
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
|
||||
.status.authenticated {
|
||||
background-color: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
.status.error {
|
||||
background-color: white;
|
||||
color: black;
|
||||
border: 2px solid black;
|
||||
}
|
||||
|
||||
|
||||
.config-table {
|
||||
border: 1px solid black;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
|
||||
.config-table th,
|
||||
.config-table td {
|
||||
border: 1px solid black;
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
||||
.config-table th {
|
||||
background-color: black;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.json-display {
|
||||
background-color: white;
|
||||
border: 1px solid black;
|
||||
@@ -141,7 +145,7 @@
|
||||
overflow-y: auto;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
|
||||
.log-panel {
|
||||
height: 200px;
|
||||
overflow-y: auto;
|
||||
@@ -150,71 +154,72 @@
|
||||
font-size: 12px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
|
||||
.log-entry {
|
||||
margin-bottom: 5px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
|
||||
.log-timestamp {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.inline-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
|
||||
.inline-buttons button {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
|
||||
.user-info {
|
||||
padding: 10px;
|
||||
border: 1px solid black;
|
||||
margin: 10px 0;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
|
||||
.user-pubkey {
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 12px;
|
||||
word-break: break-all;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
#login-section {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 768px) {
|
||||
body {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
|
||||
.inline-buttons {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
h1 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
|
||||
h2 {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>C-RELAY ADMIN API</h1>
|
||||
|
||||
|
||||
<!-- Testing Section - Always Visible -->
|
||||
<div class="section">
|
||||
<h2>DEBUG - TEST FETCH WITHOUT LOGIN</h2>
|
||||
@@ -225,7 +230,7 @@
|
||||
<div class="status disconnected" id="relay-status">READY TO FETCH</div>
|
||||
<button type="button" id="fetch-config-btn">FETCH CONFIGURATION (NO LOGIN)</button>
|
||||
<div class="status disconnected" id="config-status">NO CONFIGURATION LOADED</div>
|
||||
|
||||
|
||||
<div id="config-display" class="hidden">
|
||||
<div id="config-view-mode">
|
||||
<table class="config-table" id="config-table">
|
||||
@@ -239,7 +244,7 @@
|
||||
<tbody id="config-table-body">
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<div class="inline-buttons">
|
||||
<button type="button" id="edit-config-btn">EDIT CONFIGURATION</button>
|
||||
<button type="button" id="copy-config-btn">COPY CONFIGURATION</button>
|
||||
@@ -251,13 +256,13 @@
|
||||
<div id="config-form" class="section">
|
||||
<!-- Dynamic form will be generated here -->
|
||||
</div>
|
||||
|
||||
|
||||
<div class="inline-buttons">
|
||||
<button type="button" id="save-config-btn">SAVE & PUBLISH</button>
|
||||
<button type="button" id="cancel-edit-btn">CANCEL</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="config-raw-display">
|
||||
<h3>Raw Event JSON:</h3>
|
||||
<div class="json-display" id="raw-config-json"></div>
|
||||
@@ -273,21 +278,23 @@
|
||||
<!-- nostr-lite login UI will be injected here -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Main Interface (hidden until logged in) -->
|
||||
<div id="main-interface" class="hidden">
|
||||
|
||||
|
||||
<!-- User Info Section -->
|
||||
<div class="section">
|
||||
<h2>LOGGED IN USER</h2>
|
||||
<div class="user-info">
|
||||
<div><strong>Name:</strong> <span id="user-name">Loading...</span></div>
|
||||
<div><strong>Public Key:</strong> <div class="user-pubkey" id="user-pubkey">Loading...</div></div>
|
||||
<div><strong>Public Key:</strong>
|
||||
<div class="user-pubkey" id="user-pubkey">Loading...</div>
|
||||
</div>
|
||||
<div><strong>About:</strong> <span id="user-about">Loading...</span></div>
|
||||
</div>
|
||||
<button type="button" id="logout-btn">LOGOUT</button>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Command Section -->
|
||||
<div class="section">
|
||||
<h2>ADMIN COMMANDS</h2>
|
||||
@@ -300,20 +307,20 @@
|
||||
<option value="get_status">Get Status</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="input-group">
|
||||
<label for="command-payload">Command Payload (JSON):</label>
|
||||
<textarea id="command-payload" rows="4" placeholder='{"param": "value"}'></textarea>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="input-group">
|
||||
<label>Event Preview:</label>
|
||||
<div class="json-display" id="event-preview">No event constructed</div>
|
||||
</div>
|
||||
|
||||
|
||||
<button type="button" id="send-command-btn">SEND COMMAND</button>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Log Section -->
|
||||
<div class="section">
|
||||
<h2>EVENT LOG</h2>
|
||||
@@ -324,7 +331,7 @@
|
||||
</div>
|
||||
<button type="button" id="clear-log-btn">CLEAR LOG</button>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Load the official nostr-tools bundle first -->
|
||||
@@ -342,10 +349,10 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
// Global error handler to prevent page refreshes
|
||||
window.addEventListener('error', function(e) {
|
||||
window.addEventListener('error', function (e) {
|
||||
console.error('Global error caught:', e.error);
|
||||
console.error('Error message:', e.message);
|
||||
console.error('Error filename:', e.filename);
|
||||
@@ -354,7 +361,7 @@
|
||||
return true; // Prevent page refresh
|
||||
});
|
||||
|
||||
window.addEventListener('unhandledrejection', function(e) {
|
||||
window.addEventListener('unhandledrejection', function (e) {
|
||||
console.error('Unhandled promise rejection:', e.reason);
|
||||
e.preventDefault(); // Prevent default browser error handling
|
||||
return true; // Prevent page refresh
|
||||
@@ -399,10 +406,10 @@
|
||||
function log(message, type = 'INFO') {
|
||||
const timestamp = new Date().toISOString().split('T')[1].split('.')[0];
|
||||
const logMessage = `${timestamp} [${type}]: ${message}`;
|
||||
|
||||
|
||||
// Always log to browser console so we don't lose logs on refresh
|
||||
console.log(logMessage);
|
||||
|
||||
|
||||
// Also log to UI if elements exist
|
||||
if (logPanel) {
|
||||
const logEntry = document.createElement('div');
|
||||
@@ -418,35 +425,33 @@
|
||||
try {
|
||||
await window.NOSTR_LOGIN_LITE.init({
|
||||
theme: 'default',
|
||||
darkMode: false,
|
||||
relays: ['wss://relay.damus.io', 'wss://nos.lol'],
|
||||
methods: {
|
||||
extension: true,
|
||||
local: true,
|
||||
readonly: true,
|
||||
connect: true, // Enables "Nostr Connect" (NIP-46)
|
||||
remote: true, // Also needed for "Nostr Connect" compatibility
|
||||
otp: true // Enables "DM/OTP"
|
||||
connect: true,
|
||||
remote: true,
|
||||
otp: true
|
||||
},
|
||||
floatingTab: {
|
||||
enabled: true,
|
||||
hPosition: 0.98, // 80% from left
|
||||
vPosition: 0.00, // Top of page
|
||||
hPosition: 1, // 0.0-1.0 or '95%' from left
|
||||
vPosition: 0, // 0.0-1.0 or '50%' from top
|
||||
appearance: {
|
||||
style: 'minimal',
|
||||
theme: 'auto',
|
||||
icon: '',
|
||||
text: 'Login',
|
||||
iconOnly: false
|
||||
style: 'pill', // 'pill', 'square', 'circle', 'minimal'
|
||||
icon: '', // Clean display without icon placeholders
|
||||
text: 'Login'
|
||||
},
|
||||
behavior: {
|
||||
hideWhenAuthenticated: false,
|
||||
showUserInfo: true,
|
||||
autoSlide: false,
|
||||
persistent: false
|
||||
}
|
||||
},
|
||||
debug: true
|
||||
autoSlide: true
|
||||
},
|
||||
getUserInfo: true, // Enable profile fetching
|
||||
getUserRelay: [ // Specific relays for profile fetching
|
||||
'wss://relay.laantungir.net'
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
nlLite = window.NOSTR_LOGIN_LITE;
|
||||
@@ -462,26 +467,26 @@
|
||||
|
||||
// Handle authentication events
|
||||
function handleAuthEvent(event) {
|
||||
const {pubkey, method, error} = event.detail;
|
||||
|
||||
const { pubkey, method, error } = event.detail;
|
||||
|
||||
if (method && pubkey) {
|
||||
userPubkey = pubkey;
|
||||
isLoggedIn = true;
|
||||
console.log(`Login successful! Method: ${method}`);
|
||||
console.log(`Public key: ${pubkey}`);
|
||||
|
||||
|
||||
showMainInterface();
|
||||
loadUserProfile();
|
||||
|
||||
|
||||
// Automatically fetch configuration after login
|
||||
setTimeout(() => {
|
||||
fetchConfiguration().catch(error => {
|
||||
console.log('Auto-fetch configuration failed: ' + error.message);
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
|
||||
console.log('Login successful. Auto-fetching configuration...');
|
||||
|
||||
|
||||
} else if (error) {
|
||||
console.log(`Authentication error: ${error}`);
|
||||
}
|
||||
@@ -506,7 +511,7 @@
|
||||
// Create a SimplePool instance
|
||||
relayPool = new window.NostrTools.SimplePool();
|
||||
const relays = ['wss://relay.laantungir.net'];
|
||||
|
||||
|
||||
// Get profile event (kind 0) for the user
|
||||
const events = await relayPool.querySync(relays, {
|
||||
kinds: [0],
|
||||
@@ -549,7 +554,7 @@
|
||||
const relays = ['wss://relay.laantungir.net'];
|
||||
relayPool = null;
|
||||
}
|
||||
|
||||
|
||||
// Clean up configuration WebSocket
|
||||
if (configWebSocket) {
|
||||
console.log('Closing configuration WebSocket...');
|
||||
@@ -557,22 +562,22 @@
|
||||
configWebSocket = null;
|
||||
subscriptionId = null;
|
||||
}
|
||||
|
||||
|
||||
await nlLite.logout();
|
||||
|
||||
|
||||
userPubkey = null;
|
||||
isLoggedIn = false;
|
||||
currentConfig = null;
|
||||
|
||||
|
||||
// Reset UI
|
||||
mainInterface.classList.add('hidden');
|
||||
loginSection.classList.remove('hidden');
|
||||
updateConfigStatus(false);
|
||||
relayStatus.textContent = 'READY TO FETCH';
|
||||
relayStatus.className = 'status disconnected';
|
||||
|
||||
|
||||
console.log('Logged out successfully');
|
||||
|
||||
|
||||
} catch (error) {
|
||||
console.log('Logout failed: ' + error.message);
|
||||
}
|
||||
@@ -603,11 +608,11 @@
|
||||
async function subscribeToConfiguration() {
|
||||
try {
|
||||
console.log('=== STARTING DIRECT WEBSOCKET CONFIGURATION SUBSCRIPTION ===');
|
||||
|
||||
|
||||
if (!isLoggedIn) {
|
||||
console.log('WARNING: Not logged in, but proceeding with subscription test');
|
||||
}
|
||||
|
||||
|
||||
const url = relayUrl.value.trim();
|
||||
if (!url) {
|
||||
console.error('Please enter a relay URL');
|
||||
@@ -653,10 +658,10 @@
|
||||
reject(new Error('Connection timeout'));
|
||||
}, 10000); // 10 second timeout
|
||||
|
||||
configWebSocket.onopen = function(event) {
|
||||
configWebSocket.onopen = function (event) {
|
||||
console.log('WebSocket connection established');
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
|
||||
relayStatus.textContent = 'CONNECTED - SUBSCRIBING...';
|
||||
relayStatus.className = 'status connected';
|
||||
|
||||
@@ -683,7 +688,7 @@
|
||||
resolve(true);
|
||||
};
|
||||
|
||||
configWebSocket.onmessage = function(event) {
|
||||
configWebSocket.onmessage = function (event) {
|
||||
try {
|
||||
const message = JSON.parse(event.data);
|
||||
console.log('Received message:', message);
|
||||
@@ -704,12 +709,12 @@
|
||||
|
||||
relayStatus.textContent = 'SUBSCRIBED - LIVE UPDATES';
|
||||
relayStatus.className = 'status connected';
|
||||
|
||||
|
||||
} else if (messageType === "EOSE" && subId === subscriptionId) {
|
||||
clearTimeout(timeoutId);
|
||||
console.log('EOSE received - End of stored events');
|
||||
console.log('Current config after EOSE:', currentConfig);
|
||||
|
||||
|
||||
if (!currentConfig) {
|
||||
console.log('No configuration events were received');
|
||||
configStatus.textContent = 'NO CONFIGURATION EVENTS FOUND';
|
||||
@@ -720,22 +725,22 @@
|
||||
relayStatus.textContent = 'SUBSCRIBED - LIVE UPDATES';
|
||||
relayStatus.className = 'status connected';
|
||||
}
|
||||
|
||||
|
||||
} else if (messageType === "NOTICE") {
|
||||
console.log('Received NOTICE:', eventData || message[1]);
|
||||
|
||||
|
||||
} else if (messageType === "OK") {
|
||||
console.log('Received OK response:', message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (parseError) {
|
||||
console.error('Error parsing message:', parseError);
|
||||
console.log('Raw message data:', event.data);
|
||||
}
|
||||
};
|
||||
|
||||
configWebSocket.onerror = function(error) {
|
||||
configWebSocket.onerror = function (error) {
|
||||
clearTimeout(timeoutId);
|
||||
console.error('WebSocket error:', error);
|
||||
console.error('WebSocket URL that failed:', urlsToTry[0]);
|
||||
@@ -750,7 +755,7 @@
|
||||
reject(new Error(`WebSocket connection error to ${urlsToTry[0]}`));
|
||||
};
|
||||
|
||||
configWebSocket.onclose = function(event) {
|
||||
configWebSocket.onclose = function (event) {
|
||||
clearTimeout(timeoutId);
|
||||
console.log('WebSocket connection closed:', event.code, event.reason);
|
||||
relayStatus.textContent = 'CONNECTION CLOSED';
|
||||
@@ -764,7 +769,7 @@
|
||||
console.error('Configuration subscription failed:', error.message);
|
||||
console.error('Configuration subscription failed:', error);
|
||||
console.error('Error stack:', error.stack);
|
||||
|
||||
|
||||
relayStatus.textContent = 'SUBSCRIPTION FAILED';
|
||||
relayStatus.className = 'status error';
|
||||
return false;
|
||||
@@ -780,12 +785,12 @@
|
||||
try {
|
||||
console.log('=== DISPLAYING CONFIGURATION EVENT ===');
|
||||
console.log('Event received for display:', event);
|
||||
|
||||
|
||||
currentConfig = event;
|
||||
|
||||
|
||||
// Clear existing table
|
||||
configTableBody.innerHTML = '';
|
||||
|
||||
|
||||
// Display basic event info
|
||||
const basicInfo = [
|
||||
['Event ID', event.id],
|
||||
@@ -794,14 +799,14 @@
|
||||
['Kind', event.kind],
|
||||
['Content', event.content]
|
||||
];
|
||||
|
||||
|
||||
console.log(`Adding ${basicInfo.length} basic info rows`);
|
||||
basicInfo.forEach(([key, value]) => {
|
||||
const row = document.createElement('tr');
|
||||
row.innerHTML = `<td>${key}</td><td>${value}</td><td>-</td>`;
|
||||
configTableBody.appendChild(row);
|
||||
});
|
||||
|
||||
|
||||
// Display tags
|
||||
console.log(`Processing ${event.tags.length} tags`);
|
||||
event.tags.forEach(tag => {
|
||||
@@ -811,13 +816,13 @@
|
||||
configTableBody.appendChild(row);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Display raw JSON
|
||||
rawConfigJson.textContent = JSON.stringify(event, null, 2);
|
||||
|
||||
|
||||
console.log('Configuration display completed successfully');
|
||||
updateConfigStatus(true);
|
||||
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error in displayConfiguration:', error.message);
|
||||
console.error('Display configuration error:', error);
|
||||
@@ -832,7 +837,7 @@
|
||||
}
|
||||
|
||||
configForm.innerHTML = '';
|
||||
|
||||
|
||||
// Define field types and validation for different config parameters
|
||||
const fieldTypes = {
|
||||
'auth_enabled': 'boolean',
|
||||
@@ -897,16 +902,16 @@
|
||||
Object.entries(configData).forEach(([key, value]) => {
|
||||
const fieldType = fieldTypes[key] || 'text';
|
||||
const description = descriptions[key] || key.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
|
||||
|
||||
|
||||
const fieldGroup = document.createElement('div');
|
||||
fieldGroup.className = 'input-group';
|
||||
|
||||
|
||||
const label = document.createElement('label');
|
||||
label.textContent = description;
|
||||
label.setAttribute('for', `config-${key}`);
|
||||
|
||||
|
||||
let input;
|
||||
|
||||
|
||||
if (fieldType === 'boolean') {
|
||||
input = document.createElement('select');
|
||||
input.innerHTML = `
|
||||
@@ -923,15 +928,15 @@
|
||||
input.type = 'text';
|
||||
input.value = value;
|
||||
}
|
||||
|
||||
|
||||
input.id = `config-${key}`;
|
||||
input.name = key;
|
||||
|
||||
|
||||
// Make relay_pubkey read-only
|
||||
if (key === 'relay_pubkey' || key === 'd') {
|
||||
input.disabled = true;
|
||||
}
|
||||
|
||||
|
||||
fieldGroup.appendChild(label);
|
||||
fieldGroup.appendChild(input);
|
||||
configForm.appendChild(fieldGroup);
|
||||
@@ -945,7 +950,7 @@
|
||||
console.log('No configuration loaded to edit');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
generateConfigForm(currentConfig);
|
||||
configViewMode.classList.add('hidden');
|
||||
configEditMode.classList.remove('hidden');
|
||||
@@ -972,18 +977,18 @@
|
||||
|
||||
try {
|
||||
console.log('Building new configuration event...');
|
||||
|
||||
|
||||
// Collect form data
|
||||
const formData = new FormData();
|
||||
const formInputs = configForm.querySelectorAll('input, select');
|
||||
const newTags = [];
|
||||
|
||||
|
||||
// Preserve the 'd' tag (relay identifier) from original event
|
||||
const dTag = currentConfig.tags.find(tag => tag[0] === 'd');
|
||||
if (dTag) {
|
||||
newTags.push(dTag);
|
||||
}
|
||||
|
||||
|
||||
// Add updated configuration tags
|
||||
formInputs.forEach(input => {
|
||||
if (!input.disabled && input.name) {
|
||||
@@ -1000,11 +1005,11 @@
|
||||
content: currentConfig.content || 'C Nostr Relay Configuration'
|
||||
};
|
||||
|
||||
console.log('Signing event with nostr-lite...');
|
||||
|
||||
// Sign the event using nostr-lite
|
||||
const signedEvent = await nlLite.signEvent(newEvent);
|
||||
|
||||
console.log('Signing event with window.nostr...');
|
||||
|
||||
// Sign the event using window.nostr (NIP-07 interface)
|
||||
const signedEvent = await window.nostr.signEvent(newEvent);
|
||||
|
||||
if (!signedEvent || !signedEvent.sig) {
|
||||
throw new Error('Event signing failed - no signature returned');
|
||||
}
|
||||
@@ -1032,7 +1037,7 @@
|
||||
|
||||
// Create a new WebSocket connection for publishing
|
||||
const publishWs = new WebSocket(url);
|
||||
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let timeoutId = setTimeout(() => {
|
||||
console.error('Publish timeout');
|
||||
@@ -1040,31 +1045,31 @@
|
||||
reject(new Error('Publish timeout'));
|
||||
}, 10000);
|
||||
|
||||
publishWs.onopen = function() {
|
||||
publishWs.onopen = function () {
|
||||
console.log('Publish WebSocket connected, sending event...');
|
||||
|
||||
|
||||
// Send EVENT message
|
||||
const eventMessage = ["EVENT", signedEvent];
|
||||
console.log('Sending EVENT message:', JSON.stringify(eventMessage));
|
||||
publishWs.send(JSON.stringify(eventMessage));
|
||||
};
|
||||
|
||||
publishWs.onmessage = function(event) {
|
||||
publishWs.onmessage = function (event) {
|
||||
try {
|
||||
const message = JSON.parse(event.data);
|
||||
console.log('Publish response:', message);
|
||||
|
||||
if (Array.isArray(message)) {
|
||||
const [messageType, eventId, success, errorMsg] = message;
|
||||
|
||||
|
||||
if (messageType === "OK") {
|
||||
clearTimeout(timeoutId);
|
||||
publishWs.close();
|
||||
|
||||
|
||||
if (success) {
|
||||
console.log('Configuration published successfully!');
|
||||
console.log('The updated configuration should appear automatically via subscription');
|
||||
|
||||
|
||||
// Exit edit mode
|
||||
exitEditMode();
|
||||
resolve(true);
|
||||
@@ -1079,14 +1084,14 @@
|
||||
}
|
||||
};
|
||||
|
||||
publishWs.onerror = function(error) {
|
||||
publishWs.onerror = function (error) {
|
||||
clearTimeout(timeoutId);
|
||||
console.error('Publish WebSocket error:', error);
|
||||
publishWs.close();
|
||||
reject(new Error('Publish WebSocket error'));
|
||||
};
|
||||
|
||||
publishWs.onclose = function() {
|
||||
publishWs.onclose = function () {
|
||||
clearTimeout(timeoutId);
|
||||
};
|
||||
});
|
||||
@@ -1101,12 +1106,12 @@
|
||||
function updateEventPreview() {
|
||||
const type = commandType.value;
|
||||
const payload = commandPayload.value.trim();
|
||||
|
||||
|
||||
if (!type || !userPubkey) {
|
||||
eventPreview.textContent = 'No event constructed';
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const event = {
|
||||
kind: 1,
|
||||
pubkey: userPubkey,
|
||||
@@ -1119,13 +1124,13 @@
|
||||
id: 'EVENT_ID_PLACEHOLDER',
|
||||
sig: 'SIGNATURE_PLACEHOLDER'
|
||||
};
|
||||
|
||||
|
||||
eventPreview.textContent = JSON.stringify(event, null, 2);
|
||||
}
|
||||
|
||||
// Event handlers
|
||||
logoutBtn.addEventListener('click', logout);
|
||||
fetchConfigBtn.addEventListener('click', function(e) {
|
||||
fetchConfigBtn.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
fetchConfiguration().catch(error => {
|
||||
@@ -1133,7 +1138,7 @@
|
||||
});
|
||||
});
|
||||
|
||||
copyConfigBtn.addEventListener('click', function(e) {
|
||||
copyConfigBtn.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (currentConfig) {
|
||||
@@ -1143,13 +1148,13 @@
|
||||
}
|
||||
});
|
||||
|
||||
editConfigBtn.addEventListener('click', function(e) {
|
||||
editConfigBtn.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
enterEditMode();
|
||||
});
|
||||
|
||||
saveConfigBtn.addEventListener('click', function(e) {
|
||||
saveConfigBtn.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
saveConfiguration().catch(error => {
|
||||
@@ -1157,7 +1162,7 @@
|
||||
});
|
||||
});
|
||||
|
||||
cancelEditBtn.addEventListener('click', function(e) {
|
||||
cancelEditBtn.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
exitEditMode();
|
||||
@@ -1166,7 +1171,7 @@
|
||||
commandType.addEventListener('change', updateEventPreview);
|
||||
commandPayload.addEventListener('input', updateEventPreview);
|
||||
|
||||
sendCommandBtn.addEventListener('click', function(e) {
|
||||
sendCommandBtn.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const type = commandType.value;
|
||||
@@ -1174,11 +1179,11 @@
|
||||
console.log('Please select a command type');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
console.log(`Command sending not yet implemented: ${type}`);
|
||||
});
|
||||
|
||||
clearLogBtn.addEventListener('click', function(e) {
|
||||
clearLogBtn.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
logPanel.innerHTML = '<div class="log-entry"><span class="log-timestamp">SYSTEM:</span> Log cleared.</div>';
|
||||
@@ -1191,4 +1196,5 @@
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user