Browse Source

Implement event deletion logic with relay handling in App.svelte and add connectToRelay method in NostrClient

This commit enhances the event deletion process by introducing conditional publishing to external relays based on user roles and ownership. It also adds a new method in the NostrClient class to connect to a single relay, improving the flexibility of relay management. The version is bumped to v0.12.3 to reflect these changes.
main
mleku 3 months ago
parent
commit
27af174753
No known key found for this signature in database
  1. 33
      app/web/src/App.svelte
  2. 58
      app/web/src/nostr.js
  3. 2
      pkg/version/version

33
app/web/src/App.svelte

@ -1,6 +1,6 @@
<script> <script>
import LoginModal from './LoginModal.svelte'; import LoginModal from './LoginModal.svelte';
import { initializeNostrClient, fetchUserProfile, fetchAllEvents, fetchUserEvents, nostrClient } from './nostr.js'; import { initializeNostrClient, fetchUserProfile, fetchAllEvents, fetchUserEvents, nostrClient, NostrClient } from './nostr.js';
let isDarkTheme = false; let isDarkTheme = false;
let showLoginModal = false; let showLoginModal = false;
@ -213,7 +213,16 @@
const signedDeleteEvent = await userSigner.signEvent(deleteEventTemplate); const signedDeleteEvent = await userSigner.signEvent(deleteEventTemplate);
console.log('Signed delete event:', signedDeleteEvent); console.log('Signed delete event:', signedDeleteEvent);
// Publish the delete event to the relay // Determine if we should publish to external relays
// Only publish to external relays if:
// 1. User is deleting their own event, OR
// 2. User is admin/owner AND deleting their own event
const isDeletingOwnEvent = event.pubkey === userPubkey;
const isAdminOrOwner = (userRole === 'admin' || userRole === 'owner');
const shouldPublishToExternalRelays = isDeletingOwnEvent;
if (shouldPublishToExternalRelays) {
// Publish the delete event to all relays (including external ones)
const result = await nostrClient.publish(signedDeleteEvent); const result = await nostrClient.publish(signedDeleteEvent);
console.log('Delete event published:', result); console.log('Delete event published:', result);
@ -224,6 +233,26 @@
} else { } else {
throw new Error('No relays accepted the delete event'); throw new Error('No relays accepted the delete event');
} }
} else {
// Admin/owner deleting someone else's event - only publish to local relay
// We need to publish only to the local relay, not external ones
const localRelayUrl = `wss://${window.location.host}/ws`;
// Create a modified client that only connects to the local relay
const localClient = new NostrClient();
await localClient.connectToRelay(localRelayUrl);
const result = await localClient.publish(signedDeleteEvent);
console.log('Delete event published to local relay only:', result);
if (result.success && result.okCount > 0) {
// Remove from local list
allEvents = allEvents.filter(event => event.id !== eventId);
alert(`Event deleted successfully (local relay only - admin/owner deleting other user's event)`);
} else {
throw new Error('Local relay did not accept the delete event');
}
}
} catch (error) { } catch (error) {
console.error('Failed to delete event:', error); console.error('Failed to delete event:', error);
alert('Failed to delete event: ' + error.message); alert('Failed to delete event: ' + error.message);

58
app/web/src/nostr.js

@ -73,6 +73,61 @@ class NostrClient {
await new Promise((resolve) => setTimeout(resolve, 1000)); await new Promise((resolve) => setTimeout(resolve, 1000));
} }
async connectToRelay(relayUrl) {
console.log(`Connecting to single relay: ${relayUrl}`);
return new Promise((resolve) => {
try {
console.log(`Attempting to connect to ${relayUrl}`);
const ws = new WebSocket(relayUrl);
ws.onopen = () => {
console.log(`✓ Successfully connected to ${relayUrl}`);
resolve(true);
};
ws.onerror = (error) => {
console.error(`✗ Error connecting to ${relayUrl}:`, error);
resolve(false);
};
ws.onclose = (event) => {
console.warn(
`Connection closed to ${relayUrl}:`,
event.code,
event.reason,
);
};
ws.onmessage = (event) => {
console.log(`Message from ${relayUrl}:`, event.data);
try {
this.handleMessage(relayUrl, JSON.parse(event.data));
} catch (error) {
console.error(
`Failed to parse message from ${relayUrl}:`,
error,
event.data,
);
}
};
this.relays.set(relayUrl, ws);
// Timeout after 5 seconds
setTimeout(() => {
if (ws.readyState !== WebSocket.OPEN) {
console.warn(`Connection timeout for ${relayUrl}`);
resolve(false);
}
}, 5000);
} catch (error) {
console.error(`Failed to create WebSocket for ${relayUrl}:`, error);
resolve(false);
}
});
}
handleMessage(relayUrl, message) { handleMessage(relayUrl, message) {
console.log(`Processing message from ${relayUrl}:`, message); console.log(`Processing message from ${relayUrl}:`, message);
const [type, subscriptionId, event, ...rest] = message; const [type, subscriptionId, event, ...rest] = message;
@ -238,6 +293,9 @@ class NostrClient {
// Create a global client instance // Create a global client instance
export const nostrClient = new NostrClient(); export const nostrClient = new NostrClient();
// Export the class for creating new instances
export { NostrClient };
// IndexedDB helpers for caching events (kind 0 profiles) // IndexedDB helpers for caching events (kind 0 profiles)
const DB_NAME = "nostrCache"; const DB_NAME = "nostrCache";
const DB_VERSION = 1; const DB_VERSION = 1;

2
pkg/version/version

@ -1 +1 @@
v0.12.2 v0.12.3
Loading…
Cancel
Save